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
?
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-V, control-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 bash
ANGIO-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.
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
.
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
Usando AWK puoi fare:
awk '{ sub("\r$", ""); print }' dos.txt > unix.txt
Usando Perl puoi fare:
Perl -pe 's/\r$//' < dos.txt > unix.txt
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 ...
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.
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 .
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)
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
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)
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".
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.
Questo ha funzionato per me
tr "\r" "\n" < sampledata.csv > sampledata2.csv
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]
...
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)
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
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.
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
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.
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.
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.