Eliminar líneas vacías usando sed

350

Estoy tratando de eliminar líneas vacías usando sed:

sed '/^$/d'

pero no tengo suerte con eso.

Por ejemplo, tengo estas líneas:

xxxxxx


yyyyyy


zzzzzz

y quiero que sea así:

xxxxxx
yyyyyy
zzzzzz

¿Cuál debería ser el código para esto?

jonas
fuente
2
su comando sed se ve bien, debería funcionar
perreal
El comando anterior no funcionaría incluso si no tiene un espacio / tabulación pero terminaciones de línea CR + LF .
devnull

Respuestas:

628

Puede tener espacios o pestañas en su línea "vacía". Utilice las clases POSIX con sedpara eliminar todas las líneas que contienen solo espacios en blanco:

sed '/^[[:space:]]*$/d'

Una versión más corta que usa ERE, por ejemplo con gnu sed:

sed -r '/^\s*$/d'

(Tenga en cuenta que sed NO es compatible con PCRE).

Kent
fuente
3
@HuStmpHrrr gnu sed no es compatible con PCRE en absoluto. es ERE con-r
Kent
8
OS X necesario sed -i "" '/^[[:space:]]*$/d' <filename>,
jww
@BernieReiter ^\s*$coincidirá con todas las líneas "vacías", vacío aquí significa que la línea no contiene caracteres, o la línea solo contiene cadenas vacías (por ejemplo, espacios). Sed eliminará todas las líneas coincidentes con el dcomando.
Kent
96

Me falta la awksolución:

awk 'NF' file

Que volvería:

xxxxxx
yyyyyy
zzzzzz

¿Como funciona esto? Como NFsignifica "número de campos", las líneas que están vacías tienen 0 fiedls, de modo que awk evalúa 0 como False y no se imprime ninguna línea; sin embargo, si hay al menos un campo, la evaluación es True y hace que awkrealice su acción predeterminada: imprimir la línea actual.

fedorqui 'así que deja de dañar'
fuente
1
Whoah Incluso se está ejecutando con la versión "minimizada" de BSD de awk (versión 20121220 (FreeBSD). Gracias :-)
Bernie Reiter
@BernieReiter, de nada :) Sí, esta es una cosa idiomática muy básica que permiten todas las versiones awk.
Fedorqui 'así que deja de dañar'
Y es mucho más rápido, aunque, para una prueba rápida y sucia, invoco awk dos veces: $ time (topic companies <data.tpx | awk 'NF' - | awk -f dialog_menu.awk -) real 0m0.006s user 0m0.000s sys 0m0.008s $ time (topic companies <data.tpx | gsed '/^\s*$/d' | awk -f dialog_menu.awk -) real 0m0.014s user 0m0.002s sys 0m0.006s ¿Conocería una manera ingeniosa de incluir esto en un guión awk como, por ejemplo, un patrón? awk '/ mypattern / {do stuff ...}'
Bernie Reiter
@BernieReiter puedes decir awk 'NF {do stuff...}'.
Fedorqui 'así que deja de dañar'
1
Tenga en cuenta que esto también ignorará las líneas con espacios en blanco solamente.
wisbucky
60

sed '/^$/d'debería estar bien, ¿espera modificar el archivo en su lugar? Si es así, debe usar el-i bandera.

Tal vez esas líneas no estén vacías, así que si ese es el caso, mire esta pregunta Elimine las líneas vacías de los archivos txt, elimine los espacios desde el inicio y el final de la línea . Creo que eso es lo que está tratando de lograr.

Alberto Zaccagni
fuente
si. Estoy modificando un archivo. * .csv. ¿Cómo se debe colocar -i en el comando sed?
jonas
2
sed -i '/^$/d'Es una forma de hacerlo.
Alberto Zaccagni
49

sed

grep

awk

Oleg Mazko
fuente
1
Estos se muestran correctamente en su herramienta en línea, pero []deben no ser escaparon en una expresión entre corchetes, por lo que el código aquí no es correcto para \[\[:space:\]\]o \[ \t\]- debe ser [[:space:]]y [ \t].
Benjamin W.
1
@BenjaminW. Gracias por atrapar eso. Esos no eran del autor original, sino que provenían de Edit 3 cuando se cambió de texto normal a "código", que luego "expuso" el escape de \ \ `. Los he arreglado ahora.
wisbucky
30

Creo que este es el más fácil y rápido:

cat file.txt | grep .

Si necesita ignorar también todas las líneas de espacios en blanco, intente esto:

cat file.txt | grep '\S'

Ejemplo:

s="\
\
a\
 b\
\
Below is TAB:\
    \
Below is space:\
 \
c\
\
"; echo "$s" | grep . | wc -l; echo "$s" | grep '\S' | wc -l

salidas

7
5
Vadim
fuente
55
No es necesario cat, greptoma archivos también:grep . file.txt
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
3
Sí, lo sé, pero la pregunta inicial no mencionó si la fuente es un archivo u otra cosa, por lo que la solución es lo que viene después de "|", y antes solo un ejemplo de una fuente. Simplemente para distinguir la solución de la fuente de las líneas.
Vadim
2
grep '\S'Definitivamente no es portátil. Si es grep -Pasí, puede usarlo, grep -P '\S'pero tampoco es compatible con todas las plataformas.
tripleee
La desventaja de grep .las otras soluciones es que resaltará todo el texto en rojo. Las otras soluciones pueden preservar los colores originales. Compare unbuffer apt search foo | grep .conunbuffer apt search foo | grep -v ^$
wisbucky el
15

Con la ayuda de la respuesta aceptada aquí y la respuesta aceptada anterior, he usado:

$ sed 's/^ *//; s/ *$//; /^$/d; /^\s*$/d' file.txt > output.txt

`s/^ *//`  => left trim
`s/ *$//`  => right trim
`/^$/d`    => remove empty line
`/^\s*$/d` => delete lines which may contain white space

Esto cubre todas las bases y funciona perfectamente para mis necesidades. Felicitaciones a los carteles originales @Kent y @kev

Estafador
fuente
5

Puedes decir:

sed -n '/ / p' filename    #there is a space between '//'
tanque
fuente
.. lo que significa print all lines except the empty one(s)y cállate
Timo
2

También puedes hacer algo así usando "grep":

egrep -v "^$" file.txt
Lowbit
fuente
2

Esto funciona en awk también.

awk '!/^$/' file
xxxxxx
yyyyyy
zzzzzz
Claes Wikner
fuente
2

Lo más probable es que vea el comportamiento inesperado porque su archivo de texto se creó en Windows, por lo que la secuencia de final de línea es \r\n. Puede usar dos2unix para convertirlo a un archivo de texto de estilo UNIX antes de ejecutar sed o usar

sed -r "/^\r?$/d"

para eliminar líneas en blanco, ya sea que haya o no retorno de carro.

FauChristian
fuente
Hola, ¿qué está -rhaciendo la bandera y es posible combinarla -ipara modificar el archivo directamente y evitar imprimir en la pantalla? Además, creo que este comando también funcionaría comosed -r "/^\r$/d"
Alexander Cska
2

Otra opción sin sed, awk, perl, etc.

strings $file > $output

cadenas: imprime las cadenas de caracteres imprimibles en archivos.

usuario319660
fuente
¿Quieres decir en stringslugar de string?
Mickael B.
Hola @MickaelB. Tienes razón, lo arreglo.
user319660
0

Mi bashrespuesta específica es recomendar el uso del perloperador de sustitución con el gindicador de patrón global para esto, de la siguiente manera:

$ perl -pe s'/^\n|^[\ ]*\n//g' $file
xxxxxx
yyyyyy
zzzzzz

Esta respuesta ilustra la contabilidad de si las líneas vacías tienen o no espacios en ellas ( [\ ]*), así como el uso| para separar múltiples términos / campos de búsqueda. Probado en macOS High Sierra y CentOS 6/7.

Para su información, el código original del OP sed '/^$/d' $filefunciona bien en bashTerminal en macOS High Sierra y CentOS 6/7 Linux en un clúster de supercomputación de alto rendimiento.

justincbagley
fuente
-3

Para mí con FreeBSD 10.1 con sed funcionó solo esta solución:

sed -e '/^[     ]*$/d' "testfile"

dentro []hay símbolos de espacio y tabulación.

el archivo de prueba contiene:

fffffff next 1 tabline ffffffffffff

ffffffff next 1 Space line ffffffffffff

ffffffff empty 1 lines ffffffffffff

============ EOF =============
Vitalia
fuente