Come posso viconvertire programmaticamente (cioè, non usare ) le nuove righe DOS / Windows in Unix?
I comandi dos2unixe unix2dosnon sono disponibili su alcuni sistemi. Come posso emularli con comandi come sed/ awk/ tr?
Come posso viconvertire programmaticamente (cioè, non usare ) le nuove righe DOS / Windows in Unix?
I comandi dos2unixe unix2dosnon sono disponibili su alcuni sistemi. Come posso emularli con comandi come sed/ awk/ tr?
Risposte:
Puoi usare trper convertire da DOS in Unix; tuttavia, puoi farlo in modo sicuro solo se CR appare nel tuo file solo come primo byte di una coppia di byte CRLF. Questo di solito è il caso. Quindi utilizzare:
tr -d '\015' <DOS-file >UNIX-file
Si noti che il nome DOS-fileè diverso dal nome UNIX-file; se provi a usare lo stesso nome due volte, finirai 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-Mper inserire control-M), allora:
sed 's/^M$//' # DOS to Unix
sed 's/$/^M/' # Unix to DOS
dove '^ M' è il carattere control-M. È inoltre possibile utilizzare il meccanismo di bash quotazione ANSI-C 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, in parole povere), è molto più sensato installare i programmi di conversione (ad es. dos2unixE unix2dos, o forse dtoue utod) e usarli.
Se è necessario elaborare intere directory e sottodirectory, è possibile utilizzare zip:
zip -r -ll zipfile.zip somedir/
unzip zipfile.zip
Ciò creerà un archivio zip con terminazioni di riga modificate da CRLF a CR. unziprimetterà quindi a posto i file convertiti (e ti chiederà file per file: puoi rispondere: Sì a tutti). Ringraziamenti a @vmsnomad per averlo segnalato.
tr -d '\015' <DOS-file >UNIX-filewhere DOS-file== UNIX-filerisulta solo un file vuoto. Il file di output deve essere un file diverso, sfortunatamente.
sedopzione GNU -i(per sul posto) funziona; i limiti sono file collegati e collegamenti simbolici. Il sortcomando ha 'sempre' (dal 1979, se non in precedenza) supportato l' -oopzione che può elencare uno dei file di input. Tuttavia, ciò è in parte dovuto al fatto che sortdeve leggere tutto il suo input prima di poter scrivere qualsiasi suo output. Altri programmi supportano sporadicamente la sovrascrittura di uno dei loro file di input. È possibile trovare un programma generico (script) per evitare problemi in "L'ambiente di programmazione UNIX" di Kernighan & Pike.
sed -i $'s/\r$//' filename- per modificare sul posto. Sto lavorando su una macchina che non ha accesso a Internet, quindi l'installazione del software è un problema.
tr -d "\r" < file
dai un'occhiata 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
Utilizzare sed -iper la conversione sul posto, ad es sed -i 's/..../' file.
\r:tr "\r" "\n" < infile > outfile
-dè descritto più frequentemente e non aiuterà nella "sola \r" situazione.
\rdi \nmappatura ha l'effetto di spaziare due volte i file; ogni singola riga CRLF che termina in DOS diventa \n\nin Unix.
Farlo con POSIX è complicato:
POSIX Sed non supporta \ro \15. Anche se così fosse, l'opzione sul posto -inon è POSIX
POSIX Awk supporta \re \15, tuttavia, l' -i inplaceopzione non è POSIX
D2U e dos2unix non sono POSIX utilità , ma ex è
POSIX ex non supporta \r, \15, \no\12
Per rimuovere i ritorni a capo:
ex -bsc '%!awk "{sub(/\r/,\"\")}1"' -cx file
Per aggiungere resi di trasporto:
ex -bsc '%!awk "{sub(/$/,\"\r\")}1"' -cx file
tr\r Quindi potresti anche usare printf '%s\n' '%!tr -d "\r"' x | ex file(anche se concesso, rimosso \ranche se non immediatamente precedente \n). Inoltre, l' -bopzione per exnon è specificata da POSIX.
Puoi usare vim a livello di codice con l'opzione -c {comando}:
Dos to 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 il formato file (ff) del file nel formato di fine riga Unix / DOS
": wq" significa scrivere il file su disco ed uscire dall'editor (permettendo di usare il comando in un ciclo)
visaprà cosa :wqsignifica. Per quelli che non significano 3 caratteri 1) apri l'area di comando vi, 2) scrivi e 3) esci.
Usando AWK puoi fare:
awk '{ sub("\r$", ""); print }' dos.txt > unix.txt
Usando Perl puoi fare:
perl -pe 's/\r$//' < dos.txt > unix.txt
awk .
Per convertire un file sul posto, utilizzare
dos2unix <filename>
Per generare il testo convertito in un altro file, utilizzare
dos2unix -n <input-file> <output-file>
Puoi installarlo su Ubuntu o Debian con
sudo apt install dos2unix
o su macOS usando homebrew
brew install dos2unix
Questo problema può essere risolto con strumenti standard, ma ci sono abbastanza trappole per gli inconsapevoli che ti consiglio di installare il flipcomando, che è stato scritto più di 20 anni fa da Rahul Dhesi, l'autore di zoo. Fa un ottimo lavoro convertendo i formati di file mentre, ad esempio, evita la distruzione involontaria di file binari, il che è un po 'troppo facile se corri solo alterando ogni CRLF che vedi ...
Le soluzioni pubblicate finora affrontano solo una parte del problema, convertendo il CRLF di DOS / Windows in LF di Unix; la parte che manca è che DOS usa CRLF come separatore di linea , mentre Unix usa LF come terminatore di linea . La differenza è che un file DOS (di solito) non avrà nulla dopo l'ultima riga del file, mentre Unix lo farà. Per eseguire correttamente la conversione, è necessario aggiungere quell'LF finale (a meno che il file non abbia lunghezza zero, cioè non contenga alcuna riga). 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
Si noti che questo invia la versione Unixified del file a stdout. Se vuoi sostituire il file con una versione Unixified, aggiungi il -iflag 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))
Trasmissione incrociata da superutente .
dos2unixconverte tutti i file di input per impostazione predefinita. Il tuo utilizzo implica un -nparametro. E il reale dos2unixè un filtro che legge da stdin, scrive su stdout se i file non vengono dati.
Super duper facile con PCRE;
Come script o sostituisci $@con i tuoi file.
#!/usr/bin/env bash
perl -pi -e 's/\r\n/\n/g' -- $@
Questo sovrascriverà i tuoi file sul posto!
Consiglio di farlo solo con un backup (controllo versione o altro)
--. Ho scelto questa soluzione perché è facile da capire e adattarmi per me. Cordiali saluti, questo è ciò che fanno gli switch: -ppresuppone un ciclo "while input", -imodifica il file di input sul posto, -eesegui il seguente comando
Una soluzione awk ancora più semplice senza programma:
awk -v ORS='\r\n' '1' unix.txt > dos.txt
Tecnicamente '1' è il tuo programma, b / c awk ne richiede uno quando viene data l'opzione.
AGGIORNAMENTO : Dopo aver rivisitato questa pagina per la prima volta da molto tempo, mi sono reso conto 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
awk -v RS='\r\n' '1' dos.txt > unix.txt
awko di sedsoluzione. Inoltre, è necessario utilizzare while IFS= read -r lineper preservare fedelmente le righe di input, altrimenti viene tagliato lo spazio bianco iniziale e finale (in alternativa, non utilizzare alcun nome di variabile nel readcomando e lavorare con $REPLY).
Dovevo solo ponderare la stessa domanda (sul lato Windows, ma ugualmente applicabile a Linux). Sorprendentemente nessuno ha menzionato un modo molto automatizzato di fare la conversione CFF <-> LF per file di testo usando una buona vecchia zip -llopzione (Info-ZIP):
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. Poiunzip estrarrebbe i file come compressi, cioè con i loro nomi originali (ma con terminazioni LF), spingendo così a sovrascrivere i file originali locali se presenti.
Estratto rilevante dal zip --help:
zip --help
...
-l convert LF to CR LF (-ll CR LF to LF)
è interessante notare che nel mio git-bash su Windows sed ""ho 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 quando legge le righe dall'input e scrive sempre le terminazioni delle linee unix sull'output.
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 copie dei file, poiché questo comando modificherà i file in atto. L'opzione -c mac rende lo switch compatibile con osx.
-c mac, che è per convertire CRsolo le newline pre-OS X. Si desidera utilizzare quella modalità solo per i file da e verso Mac OS 9 o precedenti.
Puoi usare awk. Impostare il separatore record ( RS) su una regexp che corrisponda a tutti i possibili caratteri di nuova riga o caratteri. E imposta il separatore del record di output ( ORS) sul carattere newline in stile unix.
awk 'BEGIN{RS="\r|\n|\r\n|\n\r";ORS="\n"}{print}' windows_or_macos.txt > unix.txt
git diffmostra ^ M, modificato in vim)
Su Linux è facile convertire ^ M (ctrl-M) in * nix newline (^ J) con sed.
Sarà qualcosa di simile sulla CLI, ci sarà effettivamente un'interruzione di riga nel testo. Tuttavia, il \ passa quel ^ J insieme a sed:
sed 's/^M/\
/g' < ffmpeg.log > new.log
Puoi ottenere ciò usando ^ V (ctrl-V), ^ M (ctrl-M) e \ (barra rovesciata) mentre digiti:
sed 's/^V^M/\^V^J/g' < ffmpeg.log > new.log
sed --expression='s/\r\n/\n/g'
Poiché la domanda menziona sed, questo è il modo più semplice per usare sed per raggiungere questo obiettivo. Quello che dice l'espressione è sostituire tutto il ritorno a capo e l'avanzamento riga con solo avanzamento riga. Questo è ciò di cui hai bisogno quando passi da Windows a Unix. Ho verificato che funziona.
Ho creato uno script basato sulla risposta accettata in modo da poterlo convertire direttamente senza bisogno di un file aggiuntivo alla fine e rimuovere e rinominare in seguito.
convert-crlf-to-lf() {
file="$1"
tr -d '\015' <"$file" >"$file"2
rm -rf "$file"
mv "$file"2 "$file"
}
assicurati solo che se hai un file come "file1.txt" che "file1.txt2" non esiste già o verrà sovrascritto, lo uso come luogo temporaneo in cui archiviare il file.
Ho provato file 's / ^ M $ //' di sed su OSX e molti altri metodi ( http://www.thingy-ma-jig.co.uk/blog/25-11-2010/fixing- dos-line-endings o http://hintsforums.macworld.com/archive/index.php/t-125.html ). Nessuno ha funzionato, il file è rimasto invariato (tra Ctrl-v Invio era necessario per riprodurre ^ M). Alla fine ho usato TextWrangler. Non è strettamente riga di comando ma funziona e non si lamenta.
dos2unixusando il gestore pacchetti, è davvero molto più semplice ed esiste sulla maggior parte delle piattaforme.