¿Cómo puedo vi
convertir programáticamente (es decir, no usar ) nuevas líneas de DOS / Windows a Unix?
Los comandos dos2unix
y unix2dos
no están disponibles en ciertos sistemas. ¿Cómo puedo emularlos con comandos como sed
/ awk
/ tr
?
¿Cómo puedo vi
convertir programáticamente (es decir, no usar ) nuevas líneas de DOS / Windows a Unix?
Los comandos dos2unix
y unix2dos
no están disponibles en ciertos sistemas. ¿Cómo puedo emularlos con comandos como sed
/ awk
/ tr
?
Respuestas:
Puede usar tr
para convertir de DOS a Unix; sin embargo, solo puede hacerlo de manera segura si CR aparece en su archivo solo como el primer byte de un par de bytes CRLF. Este suele ser el caso. Luego usas:
tr -d '\015' <DOS-file >UNIX-file
Tenga en cuenta que el nombre DOS-file
es diferente del nombre UNIX-file
; Si intenta usar el mismo nombre dos veces, terminará sin datos en el archivo.
No puede hacerlo al revés (con el estándar 'tr').
Si sabe cómo ingresar el retorno de carro en un script ( control-V, control-Mpara ingresar control-M), entonces:
sed 's/^M$//' # DOS to Unix
sed 's/$/^M/' # Unix to DOS
donde '^ M' es el carácter control-M. También puede usar el mecanismo de bash
cotización ANSI-C para especificar el retorno de carro:
sed $'s/\r$//' # DOS to Unix
sed $'s/$/\r/' # Unix to DOS
Sin embargo, si va a tener que hacer esto con mucha frecuencia (más de una vez, en términos generales), es mucho más sensato instalar los programas de conversión (por ejemplo , dos2unix
y unix2dos
, o quizás dtou
y utod
) y usarlos.
Si necesita procesar directorios y subdirectorios completos, puede usar zip
:
zip -r -ll zipfile.zip somedir/
unzip zipfile.zip
Esto creará un archivo zip con finales de línea cambiados de CRLF a CR. unzip
luego volverá a colocar los archivos convertidos en su lugar (y le preguntará archivo por archivo; puede responder: Sí a todo). Créditos a @vmsnomad por señalar esto.
tr -d '\015' <DOS-file >UNIX-file
where DOS-file
== UNIX-file
solo da como resultado un archivo vacío. El archivo de salida tiene que ser un archivo diferente, desafortunadamente.
sed
opción GNU -i
(para el lugar) funciona; Los límites son archivos vinculados y enlaces simbólicos. El sort
comando 'siempre' (desde 1979, si no antes) admitió la -o
opción que puede enumerar uno de los archivos de entrada. Sin embargo, eso es en parte porque sort
debe leer toda su entrada antes de que pueda escribir cualquiera de sus resultados. Otros programas admiten esporádicamente sobrescribir uno de sus archivos de entrada. Puede encontrar un programa de propósito general (script) para evitar problemas en 'El entorno de programación UNIX' de Kernighan & Pike.
sed -i $'s/\r$//' filename
- para editar en su lugar. Estoy trabajando en una máquina que no tiene acceso a Internet, por lo que la instalación del software es un problema.
tr -d "\r" < file
mira aquí para ejemplos 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
Uso sed -i
para la conversión en el lugar, por ejemplo sed -i 's/..../' file
.
\r
:tr "\r" "\n" < infile > outfile
-d
se ofrece con más frecuencia y no ayudará en la "única \r
" situación.
\r
de \n
mapeo tiene el efecto de doble espacio entre los archivos; cada línea CRLF que termina en DOS se convierte \n\n
en Unix.
Hacer esto con POSIX es complicado:
POSIX Sed no es compatible con \r
o \15
. Incluso si lo hiciera, la opción en el lugar -i
no es POSIX
POSIX Awk es compatible \r
y \15
, sin embargo, la -i inplace
opción no es POSIX
d2u y dos2unix no son utilidades POSIX , pero ex es
POSIX ex no soporta \r
, \15
, \n
o\12
Para eliminar retornos de carro:
ex -bsc '%!awk "{sub(/\r/,\"\")}1"' -cx file
Para agregar retornos de carro:
ex -bsc '%!awk "{sub(/$/,\"\r\")}1"' -cx file
tr
compatible \r
. Por lo tanto, también puede usar printf '%s\n' '%!tr -d "\r"' x | ex file
(aunque está garantizado, esto se elimina \r
incluso si no precede inmediatamente \n
). Además, POSIX no especifica la -b
opción a ex
.
Puede usar vim mediante programación con la opción -c {comando}:
Dos a Unix:
vim file.txt -c "set ff=unix" -c ":wq"
Unix a dos:
vim file.txt -c "set ff=dos" -c ":wq"
"set ff = unix / dos" significa cambiar el formato de archivo (ff) del archivo al formato de final de línea Unix / DOS
": wq" significa escribir el archivo en el disco y salir del editor (permitiendo usar el comando en un bucle)
vi
sabrá lo que :wq
significa. Para aquellos que no lo hacen, los 3 caracteres significan 1) abrir el área de comando vi, 2) escribir y 3) salir.
Usando AWK puedes hacer:
awk '{ sub("\r$", ""); print }' dos.txt > unix.txt
Usando Perl puedes hacer:
perl -pe 's/\r$//' < dos.txt > unix.txt
awk
.
Para convertir un archivo en su lugar, use
dos2unix <filename>
Para enviar el texto convertido a un archivo diferente, use
dos2unix -n <input-file> <output-file>
Puede instalarlo en Ubuntu o Debian con
sudo apt install dos2unix
o en macOS usando homebrew
brew install dos2unix
Este problema se puede resolver con herramientas estándar, pero hay suficientes trampas para los incautos que recomiendo que instale el flip
comando, que fue escrito hace más de 20 años por Rahul Dhesi, el autor de zoo
. Hace un excelente trabajo al convertir formatos de archivo y, por ejemplo, evita la destrucción accidental de archivos binarios, lo cual es un poco demasiado fácil si simplemente corres alterando cada CRLF que ves ...
Las soluciones publicadas hasta ahora solo abordan parte del problema, convirtiendo el CRLF de DOS / Windows en LF de Unix; la parte que les falta es que DOS usa CRLF como separador de línea , mientras que Unix usa LF como terminador de línea . La diferencia es que un archivo DOS (generalmente) no tendrá nada después de la última línea del archivo, mientras que Unix sí. Para realizar la conversión correctamente, debe agregar ese LF final (a menos que el archivo tenga una longitud cero, es decir, no tenga líneas). Mi encantamiento favorito para esto (con una pequeña lógica agregada para manejar archivos separados por CR de estilo Mac, y no molestar a los archivos que ya están en formato unix) es un poco perl:
perl -pe 'if ( s/\r\n?/\n/g ) { $f=1 }; if ( $f || ! $m ) { s/([^\n])\z/$1\n/ }; $m=1' PCfile.txt
Tenga en cuenta que esto envía la versión Unixified del archivo a stdout. Si desea reemplazar el archivo con una versión Unixified, agregue la -i
bandera de perl .
Si no tiene acceso a dos2unix , pero puede leer esta página, puede copiar / pegar dos2unix.py desde aquí.
#!/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))
Publicación cruzada del superusuario .
dos2unix
convierte todos los archivos de entrada por defecto. Su uso implica -n
parámetro. Y lo real dos2unix
es un filtro que lee desde stdin, escribe en stdout si no se proporcionan los archivos.
Super duper fácil con PCRE;
Como secuencia de comandos, o reemplazar $@
con sus archivos.
#!/usr/bin/env bash
perl -pi -e 's/\r\n/\n/g' -- $@
¡Esto sobrescribirá sus archivos en su lugar!
Recomiendo hacer esto solo con una copia de seguridad (control de versiones o de otra manera)
--
. Elegí esta solución porque es fácil de entender y adaptar para mí. Para su información, esto es lo que hacen los interruptores: -p
asumir un bucle "mientras que la entrada", -i
editar el archivo de entrada en su lugar, -e
ejecutar el siguiente comando
Una solución awk aún más simple sin un programa:
awk -v ORS='\r\n' '1' unix.txt > dos.txt
Técnicamente '1' es su programa, b / c awk requiere uno cuando se le da la opción.
ACTUALIZACIÓN : Después de volver a visitar esta página por primera vez en mucho tiempo, me di cuenta de que nadie había publicado aún una solución interna, así que aquí hay 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
awk
o equivalente sed
. Además, debe usar while IFS= read -r line
para preservar fielmente las líneas de entrada, de lo contrario se recortará el espacio en blanco inicial y final (alternativamente, no use ningún nombre de variable en el read
comando y trabaje con $REPLY
).
Solo tenía que reflexionar sobre la misma pregunta (en el lado de Windows, pero igualmente aplicable a Linux). Sorprendentemente, nadie mencionó una forma muy automatizada de hacer la conversión CRLF <-> LF para archivos de texto usando la buena zip -ll
opción anterior (Info-ZIP):
zip -ll textfiles-lf.zip files-with-crlf-eol.*
unzip textfiles-lf.zip
NOTA: esto crearía un archivo zip conservando los nombres de archivo originales pero convirtiendo las terminaciones de línea a LF. Luego unzip
extraería los archivos como zip'ed, es decir, con sus nombres originales (pero con terminaciones LF), lo que provocaría sobrescribir los archivos originales locales, si los hubiera.
Extracto relevante de zip --help
:
zip --help
...
-l convert LF to CR LF (-ll CR LF to LF)
Curiosamente en mi git-bash en windows ya sed ""
hizo el truco:
$ 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
Supongo que sed los ignora al leer líneas de entrada y siempre escribe terminaciones de línea unix en la salida.
Para Mac osx si tiene instalado homebrew [ http://brew.sh/font>[1]
brew install dos2unix
for csv in *.csv; do dos2unix -c mac ${csv}; done;
Asegúrese de haber realizado copias de los archivos, ya que este comando modificará los archivos en su lugar. La opción -c mac hace que el conmutador sea compatible con osx.
-c mac
, que es para convertir solo CR
nuevas líneas anteriores a OS X. Desea usar ese modo solo para archivos hacia y desde Mac OS 9 o anterior.
Puedes usar awk. Establezca el separador de registros ( RS
) en una expresión regular que coincida con todos los caracteres o caracteres de nueva línea posibles. Y establezca el separador de registro de salida ( ORS
) en el carácter de nueva línea de estilo Unix.
awk 'BEGIN{RS="\r|\n|\r\n|\n\r";ORS="\n"}{print}' windows_or_macos.txt > unix.txt
git diff
muestra ^ M, editado en vim)
En Linux es fácil convertir ^ M (ctrl-M) a * nix newlines (^ J) con sed.
Será algo así en la CLI, en realidad habrá un salto de línea en el texto. Sin embargo, el \ pasa ese ^ J a sed:
sed 's/^M/\
/g' < ffmpeg.log > new.log
Obtiene esto usando ^ V (ctrl-V), ^ M (ctrl-M) y \ (barra invertida) mientras escribe:
sed 's/^V^M/\^V^J/g' < ffmpeg.log > new.log
sed --expression='s/\r\n/\n/g'
Como la pregunta menciona sed, esta es la forma más directa de usar sed para lograr esto. Lo que dice la expresión es reemplazar todo retorno de carro y avance de línea solo con avance de línea. Eso es lo que necesitas cuando pasas de Windows a Unix. Verifiqué que funciona.
Hice un script basado en la respuesta aceptada para que pueda convertirlo directamente sin necesidad de un archivo adicional al final y eliminar y cambiar el nombre después.
convert-crlf-to-lf() {
file="$1"
tr -d '\015' <"$file" >"$file"2
rm -rf "$file"
mv "$file"2 "$file"
}
solo asegúrese de que si tiene un archivo como "file1.txt" que "file1.txt2" ya no existe o se sobrescribirá, lo uso como un lugar temporal para almacenar el archivo.
Intenté sed 's / ^ M $ //' file.txt en OSX, así como varios otros métodos ( 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 ). Ninguno funcionó, el archivo permaneció sin cambios (por cierto Ctrl-v Enter fue necesario para reproducir ^ M). Al final usé TextWrangler. No es estrictamente la línea de comando, pero funciona y no se queja.
dos2unix
usando su administrador de paquetes, realmente es mucho más simple y existe en la mayoría de las plataformas.