risposta-alla-domanda-sullo-sviluppo-web-bd.com

Come convertire il newline DOS/Windows (CRLF) in Unix newline (LF) in uno script Bash?

Come posso programmare (cioè, non usando vi) convertire le newline DOS/Windows in Unix?

I comandi dos2unix e unix2dos non sono disponibili su alcuni sistemi. Come posso emularli con comandi come sed/awk/tr?

276
Koran Molovik

Puoi usare tr per convertire da DOS a Unix; tuttavia, è possibile farlo tranquillamente solo se CR appare nel file solo come primo byte di una coppia di byte CRLF. Questo di solito è il caso. Quindi usi:

tr -d '\015' <DOS-file >UNIX-file

Si noti che il nome DOS-file è diverso dal nome UNIX-file; se si tenta di utilizzare lo stesso nome due volte, si finirà con nessun dato nel file.

Non puoi farlo al contrario (con lo standard 'tr').

Se sai come inserire il ritorno a capo in uno script (control-Vcontrol-M per entrare in controllo-M), quindi:

sed 's/^M$//'     # DOS to Unix
sed 's/$/^M/'     # Unix to DOS

dove '^ M' è il carattere di controllo-M. È inoltre possibile utilizzare il meccanismo bashANGIO-C Quoting per specificare il ritorno a capo:

sed $'s/\r$//'     # DOS to Unix
sed $'s/$/\r/'     # Unix to DOS

Tuttavia, se devi farlo molto spesso (più di una volta, grosso modo), è molto più sensato installare i programmi di conversione (ad esempio dos2unix e unix2dos , o forse dtou e utod ) e usali.

299
Jonathan Leffler
tr -d "\r" < file

dai un'occhiata a qui per esempi usando sed:

# IN UNIX ENVIRONMENT: convert DOS newlines (CR/LF) to Unix format.
sed 's/.$//'               # assumes that all lines end with CR/LF
sed 's/^M$//'              # in bash/tcsh, press Ctrl-V then Ctrl-M
sed 's/\x0D$//'            # works on ssed, gsed 3.02.80 or higher

# IN UNIX ENVIRONMENT: convert Unix newlines (LF) to DOS format.
sed "s/$/`echo -e \\\r`/"            # command line under ksh
sed 's/$'"/`echo \\\r`/"             # command line under bash
sed "s/$/`echo \\\r`/"               # command line under zsh
sed 's/$/\r/'                        # gsed 3.02.80 or higher

Utilizza sed -i per la conversione sul posto, ad es. sed -i 's/..../' file.

53
ghostdog74

Fare questo con POSIX è complicato:

  • POSIX Sed non supporta \r o \15. Anche se così fosse, l'opzione -i non è POSIX

  • POSIX Awk supporta \r e \15, tuttavia -i inplace option non è POSIX

  • d2u e dos2unix non sono Utilità POSIX , ma ex è

  • POSIX ex non supporta \r, \15, \n o \12

Per rimuovere i ritorni a capo:

ex -bsc '%!awk "{sub(/\r/,\"\")}1"' -cx file

Per aggiungere ritorni a capo:

ex -bsc '%!awk "{sub(/$/,\"\r\")}1"' -cx file
36
Steven Penny

Usando AWK puoi fare:

awk '{ sub("\r$", ""); print }' dos.txt > unix.txt

Usando Perl puoi fare:

Perl -pe 's/\r$//' < dos.txt > unix.txt
20
codaddict

Questo problema può essere risolto con strumenti standard, ma ci sono un numero sufficiente di trappole per gli sprovveduti che consiglio di installare il comando flip , che è stato scritto più di 20 anni fa da Rahul Dhesi, l'autore di Zoo. Fa un ottimo lavoro nella conversione dei formati di file mentre, ad esempio, evita la distruzione involontaria dei file binari, il che è un po 'troppo facile se si corre semplicemente a modificare ogni CRLF che si vede ...

19
Norman Ramsey

Le soluzioni pubblicate finora trattano solo parte del problema, convertendo il CRLF di DOS/Windows in LF di Unix; la parte che mancano è che DOS usa CRLF come riga separatore , mentre Unix usa LF come linea terminatore . La differenza è che un file DOS (di solito) non avrà nulla dopo l'ultima riga nel file, mentre Unix lo farà. Per eseguire correttamente la conversione, è necessario aggiungere il finale LF (a meno che il file non abbia una lunghezza zero, cioè non ci siano linee in esso). Il mio incantesimo preferito per questo (con una piccola logica aggiunta per gestire i file separati da CR in stile Mac e non i file molest che sono già in formato Unix) è un po 'di Perl:

Perl -pe 'if ( s/\r\n?/\n/g ) { $f=1 }; if ( $f || ! $m ) { s/([^\n])\z/$1\n/ }; $m=1' PCfile.txt

Notare che questo invia la versione Unixified del file allo stdout. Se vuoi sostituire il file con una versione Unixified, aggiungi il flag -i di Perl.

14
Gordon Davisson

Se non hai accesso a dos2unix, ma puoi leggere questa pagina, puoi copiare/incollare dos2unix.py da qui.

#!/usr/bin/env python
"""\
convert dos linefeeds (crlf) to unix (lf)
usage: dos2unix.py <input> <output>
"""
import sys

if len(sys.argv[1:]) != 2:
  sys.exit(__doc__)

content = ''
outsize = 0
with open(sys.argv[1], 'rb') as infile:
  content = infile.read()
with open(sys.argv[2], 'wb') as output:
  for line in content.splitlines():
    outsize += len(line) + 1
    output.write(line + '\n')

print("Done. Saved %s bytes." % (len(content)-outsize))

Cross-postato da superuser .

12

Super duper facile con PCRE;

Come script, o sostituisci [email protected] con i tuoi file.

#!/usr/bin/env bash
Perl -pi -e 's/\r\n/\n/g' -- [email protected]

Questo sovrascriverà i tuoi file sul posto!

Consiglio di farlo solo con un backup (controllo della versione o altro)

8
ThorSummoner

Una soluzione awk ancora più semplice senza un programma:

awk -v ORS='\r\n' '1' unix.txt > dos.txt

Tecnicamente '1' è il tuo programma, b/c awk ne richiede uno all'atto dell'opzione. 

UPDATE: Dopo aver rivisitato questa pagina per la prima volta dopo molto tempo ho capito che nessuno ha ancora pubblicato una soluzione interna, quindi eccone una:

while IFS= read -r line;
do printf '%s\n' "${line%$'\r'}";
done < dos.txt > unix.txt
6
nawK

Puoi usare vim a livello di codice con l'opzione -c {comando}:

Da Dos a Unix:

vim file.txt -c "set ff=unix" -c ":wq"

Unix da dosare:

vim file.txt -c "set ff=dos" -c ":wq"

"set ff = unix/dos" significa cambiare fileformat (ff) del file in formato di fine linea Unix/DOS

": wq" significa scrivere il file su disco e uscire dall'editor (permettendo di usare il comando in un ciclo)

5
Johan Zicola

Per convertire un file in atto fai

dos2unix <filename>

Per produrre il testo convertito in un file diverso, fare

dos2unix -n <input-file> <output-file>

È già installato su Ubuntu ed è disponibile su homebrew con brew install dos2unix


So che la domanda richiede esplicitamente alternative a questa utility, ma questo è il primo risultato di ricerca su google per "convertire dos in unix terminazioni di riga".

4
Boris

interessante nel mio git-bash su windows sed "" ha già fatto il trucco:

$ echo -e "abc\r" >tst.txt
$ file tst.txt
tst.txt: ASCII text, with CRLF line terminators
$ sed -i "" tst.txt
$ file tst.txt
tst.txt: ASCII text

La mia ipotesi è che sed li ignori leggendo le righe dall'input e scrive sempre unix terminazioni di linea in uscita.

4
user829755

Questo ha funzionato per me 

tr "\r" "\n" < sampledata.csv > sampledata2.csv 
3
Santosh

TIMTOWTDI!

Perl -pe 's/\r\n/\n/; s/([^\n])\z/$1\n/ if eof' PCfile.txt

Basato su @GordonDavisson

Bisogna considerare la possibilità di [noeol] ...

2
lzc

Dovevo solo ponderare la stessa domanda (sul lato Windows, ma ugualmente applicabile a linux.) Sorprendentemente nessuno ha menzionato un modo molto automatizzato di fare CRLF <-> conversione LF per i file di testo usando la buona vecchia opzione Zip -ll (Informazioni -Cerniera lampo):

Zip -ll textfiles-lf.Zip files-with-crlf-eol.*
unzip textfiles-lf.Zip 

NOTA: questo creerebbe un file Zip preservando i nomi dei file originali ma convertendo le terminazioni di linea in LF. Quindi unzip estrae i file come Zip'ed, cioè con i loro nomi originali (ma con terminazioni LF), chiedendo quindi di sovrascrivere i file originali locali, se presenti.

Estratto pertinente da Zip --help:

Zip --help
...
-l   convert LF to CR LF (-ll CR LF to LF)
2
vmsnomad

Puoi usare awk. Imposta il separatore di record (RS) su un'espressione regolare che corrisponda a tutti i possibili caratteri di nuova riga o caratteri. E imposta il separatore dei record di output (ORS) sul carattere di nuova riga di tipo unix.

awk 'BEGIN{RS="\r|\n|\r\n|\n\r";ORS="\n"}{print}' windows_or_macos.txt > unix.txt
1
kazmer

Per Mac osx se hai installato homebrew [ http://brew.sh/][1]

brew install dos2unix

for csv in *.csv; do dos2unix -c mac ${csv}; done;

Assicurati di aver fatto delle copie dei file, dato che questo comando modificherà i file in posizione . L'opzione -c mac rende lo switch compatibile con osx.

1
Ashley Raiteri

Su Linux è facile convertire ^ M (ctrl-M) in * nix newlines (^ J) con sed.

Sarà qualcosa di simile sulla CLI, ci sarà effettivamente un'interruzione di riga nel testo. Tuttavia, il\passa quello ^ J insieme a sed:

sed 's/^M/\
/g' < ffmpeg.log > new.log

Puoi ottenere ciò usando ^ V (ctrl-V), ^ M (ctrl-M) e\(backslash) mentre scrivi:

sed 's/^V^M/\^V^J/g' < ffmpeg.log > new.log
1
jet

Come estensione della soluzione Unix a DOS di Jonathan Leffler, per convertire in sicurezza in DOS quando non si è sicuri delle terminazioni di riga del file corrente:

sed '/^M$/! s/$/^M/'

Questo controlla che la riga non finisca già in CRLF prima di convertirsi in CRLF.

0
Gannet

Ho creato uno script basato sulla risposta accettata in modo da poterlo convertire direttamente senza bisogno di un file aggiuntivo alla fine e rimuovendolo e rinominandolo in seguito.

convert-crlf-to-lf() {
    file="$1"
    tr -d '\015' <"$file" >"$file"2
    rm -rf "$file"
    mv "$file"2 "$file"
}

assicurati che se hai un file come "file1.txt" che "file1.txt2" non esiste già o verrà sovrascritto, io lo uso come luogo temporaneo in cui archiviare il file.

0
OZZIE
sed --expression='s/\r\n/\n/g'

Poiché la domanda menziona sed, questo è il modo più diretto per usare sed per raggiungere questo obiettivo. Quello che dice l'espressione è sostituire tutto il carriage-return e il line-feed con solo il solo line feed. Questo è quello che ti serve quando vai da Windows a Unix. Ho verificato che funziona.

0
John Paul