¿Se pueden eliminar los caracteres de doble línea 'dobles'?

25

Tengo un documento con muchas líneas vacías.

¿Cómo puedo eliminarlos cuando hay 2 o más juntos?

Intenté el sed "s/\n\n//"archivo pero no funcionó. No hay error.

Michael Durrant
fuente
3
¿Le leo correctamente si no desea eliminar todas las líneas en blanco, pero solo si son dos o más? Así que no solo líneas en blanco?
Runium
1
Y si se trata de dos o más líneas, ¿se eliminarán realmente todas o solo todas menos una?
Hauke ​​Laging

Respuestas:

42

Solo para eliminar líneas vacías:

sed  '/^$/d'

sedestá orientado a líneas, por lo que pensar en términos de "2 o más de un byte particular" funciona, excepto cuando ese byte es una nueva línea. Entonces tienes que pensar en algo que funcione para toda la línea.

Bruce Ediger
fuente
¡Por supuesto! +1 para elegancia simple.
terdon
2
sedes capaz de manejar varias líneas a través de su función "espacio de patrón" / "espacio de espera". Pero siento que es demasiado complicado. ;-)
Hauke ​​Laging
Esto no funcionará como se desea si el primer carácter del archivo es una nueva línea.
Chris Down
1
Para que funcione cuando el primer carácter es un carácter de nueva línea (si eso es realmente un requisito), entonces se puede encerrar el comando con una dirección negativa 1!(que coincida con todos, excepto la línea 1), de este modo: sed '1!{/^$/d'}.
Toby Speight
1
@AaronFranke: sí, pero esa es una faceta de cómo los shells de Linux tratan la redirección '>'. El shell mira la línea de comando, ve una redirección '>' de stdout a un archivo, crea ese archivo y solo entonces se ejecuta sed. La creación de un archivo esencialmente eliminará cualquier archivo existente con el mismo nombre. sed '/^&/d' file.txt > otherfile.txttrabajará.
Bruce Ediger
24

No hay necesidad de sed. grephará:

grep .

(es decir grep, SPC, punto, es decir, coincide con cualquier línea que contenga al menos un carácter).

También hay:

tr -s '\n'

(exprima cualquier secuencia de caracteres de nueva línea en uno).

Como señaló Chris, ambos no son equivalentes porque eliminar líneas vacías (como la primera solución anterior y la mayoría de las otras respuestas se centran aquí) no es lo mismo que exprimir secuencias de caracteres de nueva línea como se solicita en el caso donde la primera línea está vacía. solo se necesita un carácter de nueva línea para dejar vacía la primera línea.

Stéphane Chazelas
fuente
2
Esto no funcionará como se desea si el primer carácter del archivo es una nueva línea: sprunge.us/FLAJ
Chris Down
7

sedno es la mejor herramienta para eso, ya que se basa en líneas y trata \ncomo el carácter de final de línea, esto se complica.Habiendo visto la respuesta de @Bruce Ediger, sedpuede ser la herramienta perfecta para el trabajo, aún así, aquí hay algunas otras opciones:

  1. Perl

    perl -ne 'print if /./' file.txt
    

    o

    perl -pe '$/=""; s/\n+/\n/;' file.txt 
    

    Gracias a @ruakh que me hizo ir y leer esto :

    PS

    El separador de registro de entrada, nueva línea por defecto. Esto influye en la idea de Perl de lo que es una "línea". Funciona como la variable RS de awk, incluido el tratamiento de líneas vacías como un terminador si se establece en la cadena nula (una línea vacía no puede contener espacios ni pestañas). Puede configurarlo en una cadena de caracteres múltiples para que coincida con un terminador de caracteres múltiples, o en undef para leer hasta el final del archivo. Establecerlo en "\ n \ n" significa algo ligeramente diferente a establecerlo en "", si el archivo contiene líneas vacías consecutivas. La configuración en "" tratará dos o más líneas vacías consecutivas como una sola línea vacía. Establecer "\ n \ n" supondrá ciegamente que el siguiente carácter de entrada pertenece al siguiente párrafo, incluso si se trata de una nueva línea.

  2. gawk / awk

    awk '$1' file.txt
    

    Eso funcionará para el ejemplo publicado, pero como señaló @Stephane Chazelas , también eliminará las líneas cuyo primer campo "parezca" 0. Esto es más robusto:

    awk NF file.txt
    
terdon
fuente
Para Perl, perl -pe 's/\n+/\n/ file.txtsí, el separador de registro de entrada es irrelevante para este uso.
vonbrand
@vonbrand no, perl -peo perl -netrabajar línea por línea. \n+nunca coincidirá porque solo se aplica en una sola línea. Es por eso que usted necesita alguno de los conjuntos $/o utilizar -0TI sLuRp el archivo de conjunto: perl -0pe 's/\n+/\n/' file.
terdon
6

¿Qué quieres decir con eliminar? eliminar duplicado (muchas líneas en blanco a una) o eliminar todo?

Si desea eliminar duplicados, este es el método que usa sed:

sed '$!N; /^\(.*\)\n\1$/!P; D'

Simula uniqcomando.

La mejor opción es usar awk:

awk NF <filename>
Cuonglm
fuente
¡La sedparte de esto funciona muy bien! Recomiendo esta como la mejor respuesta.
Akito
2

Para la mayoría de estas respuestas, primero es necesario eliminar los espacios en blanco finales. Al eliminar las líneas nuevas duplicadas, se eliminan todas las líneas en blanco. (Piensa sobre esto).

Interpretado literalmente, el OP quiere que "se eliminen todas las líneas en blanco de un archivo si hay líneas en blanco repetidas".

El usuario típico quiere "eliminar solo las líneas en blanco duplicadas".

Para hacer esto, primero elimine el espacio en blanco al final y canalice a través de cat -s

sed  s/[[:space:]]*$// | cat -s

Y, sin embargo, esto no eliminará una línea en blanco inicial o posterior superfluo.

mckenzm
fuente
Votado negativamente, pero esto claramente funciona? Sin comentarios ?
mckenzm
1
Te voté por ... ya sabes ... respondiendo la pregunta. =) No puedo creer que la respuesta de Bruce Ediger haya sido votada cuando elimina cada línea en blanco. Si alguien pregunta cómo eliminar líneas en blanco duplicadas, no puedo imaginar ningún escenario en el que eliminar todas las líneas en blanco sea una solución aceptable. Pero lo que sea. Hay una página en el sitio web para sed que cubre esto, por cierto: gnu.org/software/sed/manual/sed.html#cat-_002ds
Todd Walton
2

Si desea mantener una sola línea en blanco para cualquier secuencia dada de líneas en blanco, puede hacer lo siguiente:

sed -e '/./b' -e :n -e 'N;s/\n$//;tn'
mikeserv
fuente
1
Esta es la única respuesta (además cat -s) que realmente cumple exactamente lo que se hizo la pregunta tal como la entiendo. (Y es mejor que cat -sporque puedo usarlo sed -i)
Matthew
-2

Intente sed -e 's#\\n\\n#\\n#g' input.file > output.fileusar /ambos como separador de campo y parte de su expresión regular podría ser el problema.

linuxrebel
fuente
2
Acabo de darle un giro a uno de mis archivos que contiene líneas nuevas dobles y triples en una secuencia. No funciona en absoluto para mí.
syntaxerror
-3

Usa este comando:

tr -s '\r' '\n'
maullar
fuente
Sí, su respuesta no funcionó para mí.
miau
55
AFAIK esta respuesta es incorrecta. Te recomiendo que lo elimines.
zuazo
oh, es porque mi archivo contiene muchas líneas nuevas y retornos de carro en realidad. 0x0d0a
miau
2
En realidad, el comando elimina líneas repetidas con el final de línea de Windows. Prueba con echo -e 'one\r\n\r\n\r\n\rtwo'| tr -s '\r' '\n'. El comando trse traducirá todo \ra \ny luego la comprime todo \na una sola. Entonces, funciona, no estoy seguro de qué hacer con el hecho de que esto se aplica a Windows, no a UNIX.