¿Cómo eliminar líneas duplicadas con awk manteniendo líneas vacías?

13

El siguiente awkcomando elimina todas las líneas duplicadas como se explica aquí :

awk '!seen[$0]++'

Si el texto contiene líneas vacías, se eliminarán todas menos una línea vacía.

¿Cómo puedo mantener todas las líneas vacías mientras elimino todas las líneas duplicadas no vacías, usando solo awk? Por favor, también incluya una breve explicación.

Serge Stroobandt
fuente

Respuestas:

28

Otra opción es verificar NF, por ejemplo:

awk '!NF || !seen[$0]++'
Thor
fuente
11

Alternativamente

awk '!/./ || !seen[$0]++' file

El truco principal es el mismo, seen[$0]++crea una entrada en la seenmatriz asociativa cuya clave es la línea actual ( $0). Por lo tanto, !seen[$0]++será falso si esta línea ya se ha visto. El /./está comprobando si la línea contiene caracteres no en blanco, por lo que !/./coincide con las líneas que no están en blanco. Combinado con || !seen[$0]++él, ignorará todas las líneas duplicadas, excepto las en blanco, e imprimirá el resto.

terdon
fuente
Creo que esta debería haber sido la respuesta aceptada. +1 para explicación!
SS Anne
5
awk '/^[[:blank:]]*$/ { print; next; }; !seen[$0]++'

Todo lo que tiene que hacer es buscar primero una línea vacía (realmente vacía o simplemente en blanco).

Hauke ​​Laging
fuente
5

Aquí hay otra awksolución, similar a la respuesta de @ Thor, menos concisa pero más eficiente:

awk '!NF {print;next}; !($0 in a) {a[$0];print}' file

Con esto, solo verificamos si a[$0]ha existido o no. Si no, inicializándolo, luego imprima. En este caso, no tenemos ninguna referencia, asignación a a[$0]si existiera.

Cuonglm
fuente
No medí ninguna diferencia de tiempo significativa con mi archivo de prueba de 288 líneas. Sin embargo, su código ciertamente atrapa el premio por ser el más legible.
Serge Stroobandt