Reemplazar dos CR consecutivos por uno

Reemplazar dos CR consecutivos por uno

cat -e file.txtda:

{"yellow":"mango"}^M$
^M$
{"yellow":"banana"}^M$
^M$
{"yellow":"blabla"}^M$
^M$

y me gustaría simplemente tener:

{""yellow":"mango"}^M$
{"yellow":"banana"}^M$
{"yellow":"blabla"}^M$

implementado para todos los archivos con extensión txt en la carpeta. Entonces lo intenté:

find . -type f -name "*.txt" -print0 | xargs -0 sed -i "s/^M$^M$/^M$/g"

en vano. ¿Alguien tiene una idea mejor?

head -n 3 file.txt | od -bc

rendimientos:

0000000 173 042 171 145 154 154 157 167 042 072 042 155 141 156 147 157
          {   "   y   e   l   l   o   w   "   :   "   m   a   n   g   o
0000020 042 175 015 012 015 012 173 042 142 141 142 141 142 042 072 042
          "   }  \r  \n  \r  \n   {   "   b   a   b   a   b   "   :   "
0000040 155 141 156 147 157 042 175 015 012
          m   a   n   g   o   "   }  \r  \n
0000051

este:

awk 1 RS='\r\n' ORS= < file.txt

elimina las nuevas líneas por completo (por lo que no es bueno: quiero mantener una de las dos sucesivas en cada línea, pero hace algo).

Respuesta1

Puedes usar sed -z 's/\r\n\r\n/\r\n/g'.

Normalmente sedsólo funciona en una línea a la vez. Al usar la -zopción, sedfuncionará en líneas, que están separadas por 0bytes, que normalmente no existen en un archivo de texto, por lo que todo el archivo se tratará como una sola línea y las nuevas líneas se pueden reemplazar.

(encontrado endesbordamiento de pilay explicación adicional)

Respuesta2

También puede eliminar líneas que contengan únicamente el retorno de carro.

  • Con GNU Sed:

    sed '/^\r$/d' file
    
  • Para una máquina mínima pero compatible con POSIX (aquí necesitamos generar el retorno de carro con Printf):

    sed "/^$(printf "\r")$/d" file
    

^coincide con el inicio de línea y el último $, el final de línea ( \n).

Por ejemplo:

$ cat -e file
AB^M$
^M$
CB^M$
^M$
$ sed '/^\r$/d' file|cat -e
AB^M$
CB^M$

Respuesta3

Si está bien eliminar todas las líneas en blanco, puede hacer:

perl -wlne '/\S/ and print' old_file > new_file

Y si prefiere sobrescribir su(s) archivo(s), puede usar el -iinterruptor (in situ):

perl -wlni.bak -e '/\S/ and print' file1 file2 file3 ...

La línea anterior copiará los archivos originales como *.bakarchivos. Si no te importa tener copias de seguridad, puedes omitir la .bakparte, como esta:

perl -wlni -e '/\S/ and print' file1 file2 file3 ...

(Incluso puedes usar comodines, así que en lugar de file1 file2 file3 ...puedes escribir file*.)

La ventaja de este enfoque es que realiza cambios en sus archivos todos a la vez (en lugar de tener que ejecutarlo una vez para cada archivo).

Pero recuerde: esto solo mantendrá las líneas que contengan al menos un carácter que no sea un espacio en blanco. Entonces, si una línea consta solo de cinco espacios, una tabulación, un retorno de carro y un carácter de salto de línea, no se conservará.

Respuesta4

Usando Raku (el lenguaje anteriormente conocido como Perl6)

~$ raku -ne '.put if /\S/ ;' test_blank.txt
{"yellow":"mango"}
{"yellow":"banana"}
{"yellow":"blabla"}

El ejemplo anterior solo imprime líneas que contienen caracteres que no son espacios en blanco ( \Scoincide con un solo carácter que no es un espacio en blanco). Una versión muy legible a continuación:

~$ raku -ne '.put if .chars;' test_blank.txt
{"yellow":"mango"}
{"yellow":"banana"}
{"yellow":"blabla"}

HTH.

https://raku.org
https://rakudo.org/downloads

información relacionada