Rimuovere il ritorno a capo in Unix


Risposte:


261

Ho intenzione di assumere che si ritorni a capo medi ( CR, "\r", 0x0d) alle estremità delle linee piuttosto che solo alla cieca all'interno di un file (potrebbe essere li nel mezzo di stringhe per quanto ne so). Utilizzo di questo file di test con CRa solo alla fine della prima riga:

$ cat infile
hello
goodbye

$ cat infile | od -c
0000000   h   e   l   l   o  \r  \n   g   o   o   d   b   y   e  \n
0000017

dos2unix è la strada da percorrere se è installato sul tuo sistema:

$ cat infile | dos2unix -U | od -c
0000000   h   e   l   l   o  \n   g   o   o   d   b   y   e  \n
0000016

Se per qualche motivo dos2unixnon è disponibile per te, sedlo farà:

$ cat infile | sed 's/\r$//' | od -c
0000000   h   e   l   l   o  \n   g   o   o   d   b   y   e  \n
0000016

Se per qualche motivo sednon è disponibile per te, edlo farà, in modo complicato:

$ echo ',s/\r\n/\n/
> w !cat
> Q' | ed infile 2>/dev/null | od -c
0000000   h   e   l   l   o  \n   g   o   o   d   b   y   e  \n
0000016

Se non hai nessuno di quegli strumenti installati sulla tua scatola, hai problemi più grandi rispetto al tentativo di convertire i file :-)


13
\rfunziona solo con GNU sed, altrimenti puoi farlo:sed `echo "s/\r//"`
lapo

15
sedechoriconoscere \rsu MacOS. In questo caso printf "\r"sembra funzionare solo.
Steve Powell,

30
Per elaborare il commento di @ steve: su un Mac, utilizzare quanto segue: sed "s/$(printf '\r')\$//"
mklement0

7
Per risolvere il problema su Mac puoi anche aggiungere il prefisso della stringa sed a virgoletta singola in questo $modo: sed $'s@\r@@g' |od -c (ma se dovessi sostituirlo con \nte dovresti fuggire)
nhed

1
Non sono sicuro al 100%, ma per OS X, l'utilizzo CTRL-V + CTRL-Mal posto di \rsembra che funzioni.

240
tr -d '\r' < infile > outfile

Vedi tr (1)


4
Non eccezionale: 1. non funziona sul posto, 2. può sostituire anche in EOL (che può essere o meno quello che vuoi ...).
Tomasz Gandor,

10
1. La maggior parte degli strumenti unixy funzionano in questo modo, ed è di solito il modo più sicuro di procedere poiché se rovini hai ancora l'originale. 2. La domanda, come indicato, è rimuovere i ritorni a capo, non convertire i finali di riga. Ma ci sono molte altre risposte che potrebbero servirti meglio.
Henrik Gustafsson,

1
Se il tuo trnon supporta la \rfuga, prova '\015'o forse un valore letterale '^M'(in molte shell su molti terminali, ctrl-V ctrl-M produrrà un carattere letterale ctrl-M).
Tripleee,

Quindi come si cambia quando vuoi outfile = infile?
Christopher

3
@donlan, risposta in ritardo, ma di solito si usa qualcosa come: someProg <in >out && mv out in.
paxdiablo,

38

Vecchia scuola:

tr -d '\r' < filewithcarriagereturns > filewithoutcarriagereturns

32

Il modo più semplice su Linux è, secondo la mia modesta opinione,

sed -i 's/\r$//g' <filename>

Le virgolette attorno all'operatore di sostituzione 's/\r//'sono essenziali . Senza di essi, la shell interpreterà \rcome escape + r, la ridurrà in piano re rimuoverà tutte le lettere minuscole r. Ecco perché la risposta data sopra nel 2009 da Rob non funziona.

E l'aggiunta del /gmodificatore assicura che anche multipli\r verranno rimossi , e non solo il primo.



7

sed -i s/\r// <filename>o somesuch; vedere man sedo la ricchezza di informazioni disponibili sul web relative all'uso di sed.

Una cosa da sottolineare è il significato preciso di "ritorno a capo" di cui sopra; se intendi veramente il singolo carattere di controllo "ritorno a capo", il modello sopra è corretto. Se intendevi, più in generale, CRLF (ritorno a capo e un avanzamento riga, ovvero come vengono implementati gli avanzamenti riga in Windows), probabilmente vorrai \r\ninvece sostituire . I feed di linea nuda (newline) in Linux / Unix sono \n.


Sto cercando di usare -> sed 's / \ r \ n / = /' countryNew.txt> demo.txt che non funziona. "tigre" "Leone".
Suvasis,

dobbiamo intenderlo per significare che sei su un mac? Ho notato che Darwin sed sembra avere comandi e set di funzionalità diversi per impostazione predefinita rispetto alla maggior parte delle versioni di Linux ...
jsh

4
Cordiali saluti, il s/\r//non sembra rimuovere i ritorni a capo su OS X, sembra rinvece rimuovere caratteri letterali . Non sono sicuro del perché. Forse ha qualcosa a che fare con il modo in cui viene citata la stringa? Come soluzione alternativa, l'utilizzo CTRL-V + CTRL-Mal posto di \rsembra funzionare.

6

Se sei un utente Vi, puoi aprire il file e rimuovere il ritorno a capo con:

:%s/\r//g

o con

:1,$ s/^M//

Si noti che è necessario digitare ^ M premendo ctrl-v e quindi ctrl-m.


2
Non eccezionale: se il file ha CR su ogni riga (cioè è un file DOS corretto), vim lo caricherà con filetype = dos e non mostrerà affatto ^M-s. Aggirare questo è una tonnellata di tasti, che non è ciò per cui è fatto Vim;). Vorrei solo provare sed -i, e quindi `-e 's / \ r $ // g' per limitare la rimozione ai CR presso EOL.
Tomasz Gandor,

6

Ancora una volta una soluzione ... Perché ce n'è sempre un'altra:

perl -i -pe 's/\r//' filename

È bello perché è a posto e funziona in tutti i gusti di unix / linux con cui ho lavorato.


3

Qualcun altro lo consiglia dos2unixe lo consiglio vivamente anche io. Sto solo fornendo maggiori dettagli.

Se installato, vai al passaggio successivo. Se non è già installato, consiglierei di installarlo yumcome:

yum install dos2unix

Quindi puoi usarlo come:

dos2unix fileIWantToRemoveWindowsReturnsFrom.txt

2

Se stai usando un sistema operativo (come OS X) che non ha il dos2unixcomando ma ha un interprete Python (versione 2.5+), questo comando è equivalente al dos2unixcomando:

python -c "import sys; import fileinput; sys.stdout.writelines(line.replace('\r', '\n') for line in fileinput.input(mode='rU'))"

Questo gestisce sia i file con nome sulla riga di comando sia i pipe e i reindirizzamenti, proprio come dos2unix. Se aggiungi questa linea al tuo file ~ / .bashrc (o file di profilo equivalente per altre shell):

alias dos2unix="python -c \"import sys; import fileinput; sys.stdout.writelines(line.replace('\r', '\n') for line in fileinput.input(mode='rU'))\""

... la prossima volta che accedi (o esegui source ~/.bashrcnella sessione corrente) sarai in grado di usare il dos2unixnome sulla riga di comando nello stesso modo degli altri esempi.


2

Ecco la cosa,

%0dè il carattere di ritorno a capo. Per renderlo compatibile con Unix. Dobbiamo usare il comando seguente.

dos2unix fileName.extension fileName.extension


1

prova questo per convertire il file DOS in file unix:

file fromdos


1

Per UNIX ... ho notato che dos2unix ha rimosso le intestazioni Unicode dal mio file UTF-8. Sotto git bash (Windows), il seguente script sembra funzionare bene. Usa sed. Nota rimuove solo i ritorni a capo alle estremità delle linee e conserva le intestazioni Unicode.

#!/bin/bash

inOutFile="$1"
backupFile="${inOutFile}~"
mv --verbose "$inOutFile" "$backupFile"
sed -e 's/\015$//g' <"$backupFile" >"$inOutFile"

1

Se si esegue un ambiente X e si dispone di un editor appropriato (codice Visual Studio), seguirei la raccomandazione:

Codice di Visual Studio: come mostrare le terminazioni di riga

Basta andare nell'angolo in basso a destra dello schermo, il codice di Visual Studio ti mostrerà sia la codifica del file che la convenzione di fine riga seguita dal file, con un semplice clic puoi cambiarlo.

Usa semplicemente il codice visivo come sostituto di notepad ++ in un ambiente Linux e sei pronto per partire.


Oppure usa Notepad++il comando 's Edit / EOL Conversion / Unix (LF)sul tuo sistema Windows prima di copiare il file sul tuo sistema Linux.
Jesse Chisholm,

1

Rimozione \rsu qualsiasi sistema UNIX®:

La maggior parte delle soluzioni esistenti in questa domanda sono specifiche di GNU e non funzionerebbero su OS X o BSD; le soluzioni sottostanti dovrebbero funzionare su molti più sistemi UNIX, e in qualsiasi shell, da tcsha sh, eppure funzionare anche su GNU / Linux.

Testato su OS X, OpenBSD e NetBSD in tcsh, e su Debian GNU / Linux in bash.


Con sed:

In tcshsu un OS X, il seguente sedframmento di codice potrebbe essere utilizzato insieme printf, in quanto né sedechomanico \rin modo speciale come la GNU fa:

sed `printf 's/\r$//g'` input > output

Con tr:

Un'altra opzione è tr:

tr -d '\r' < input > output

Differenza tra sede tr:

Sembrerebbe che trpreservi la mancanza di una nuova riga finale dal file di input, mentre sedsu OS X e NetBSD (ma non su OpenBSD o GNU / Linux) inserisce una nuova riga finale alla fine del file anche se nell'input manca qualche finale \ro \nalla fine del file.


test:

Ecco alcuni test di esempio che potrebbero essere utilizzati per garantire che funzioni sul tuo sistema, usando printfe hexdump -C; in alternativa, od -cpotrebbe essere utilizzato anche in mancanza del sistema hexdump:

% printf 'a\r\nb\r\nc' | hexdump -C
00000000  61 0d 0a 62 0d 0a 63                              |a..b..c|
00000007
% printf 'a\r\nb\r\nc' | ( sed `printf 's/\r$//g'` /dev/stdin > /dev/stdout ) | hexdump -C
00000000  61 0a 62 0a 63 0a                                 |a.b.c.|
00000006
% printf 'a\r\nb\r\nc' | ( tr -d '\r' < /dev/stdin > /dev/stdout ) | hexdump -C
00000000  61 0a 62 0a 63                                    |a.b.c|
00000005
% 

0

Ho usato Python per questo, qui il mio codice;

end1='/home/.../file1.txt'
end2='/home/.../file2.txt'
with open(end1, "rb") as inf:
     with open(end2, "w") as fixed:
        for line in inf:
            line = line.replace("\n", "")
            line = line.replace("\r", "")
            fixed.write(line)

0

Anche se è un post più vecchio, recentemente ho riscontrato lo stesso problema. Dato che avevo tutti i file da rinominare all'interno di / tmp / blah_dir / dato che ogni file in questa directory aveva il carattere finale "/ r" (che mostra "?" Alla fine del file), quindi fare lo script in modo che solo io potevo pensare.

Volevo salvare il file finale con lo stesso nome (senza trascinare alcun carattere). Con sed, il problema era il nome del file di output di cui avevo bisogno per menzionare qualcos'altro (che non volevo).

Ho provato altre opzioni come suggerito qui (non considerato dos2unix a causa di alcune limitazioni) ma non ha funzionato.

Ho provato con "awk" che ha funzionato dove ho usato "\ r" come delimitatore e ho preso la prima parte :

il trucco è:

echo ${filename}|awk -F"\r" '{print $1}'

Sotto lo snippet di script ho usato (dove avevo tutti i file con "\ r" come carattere finale nel percorso / tmp / blah_dir /) per risolvere il mio problema:

cd /tmp/blah_dir/
for i in `ls`
  do
    mv   $i     $(echo $i | awk -F"\r" '{print $1}')
done

Nota: questo esempio non è molto esatto anche se vicino a quello che ho lavorato (menzionando qui solo per dare un'idea migliore di ciò che ho fatto)


0

Ho creato questo shell-script per rimuovere il carattere. Funziona in Solaris e Red Hat:

#!/bin/ksh

LOCALPATH=/Any_PATH

for File in `ls ${LOCALPATH}`
do
   ARCACT=${LOCALPATH}/${File}
   od -bc ${ARCACT}|sed -n 'p;n'|sed 's/015/012/g'|awk '{$1=""; print $0}'|sed 's/ /\\/g'|awk '{printf $0;}'>${ARCACT}.TMP
   printf "`cat ${ARCACT}.TMP`"|sed '/^$/d'>${ARCACT}
   rm ${ARCACT}.TMP
done

exit 0

-1

puoi semplicemente farlo:

$ echo $(cat input) > output

Non so perché qualcuno abbia dato '-1'. Questa è una risposta perfettamente valida (e l'unica che ha funzionato per me).
FractalSpace

1
Oh, scusa, sono stato io. Aspetta, guarda, non funziona davvero per "\ r"!
Viacheslav Rodionov,

1
@FractalSpace Questa è un'idea terribile! Distrugge completamente tutta la spaziatura nel file e lascia tutto il contenuto del file soggetto all'interpretazione della shell. Provalo con un file che contiene una riga a * b...
Tom Fenech,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.