Comment supprimer les lignes en double avec awk tout en gardant les lignes vides?

13

La awkcommande ci-dessous supprime toutes les lignes en double comme expliqué ici :

awk '!seen[$0]++'

Si le texte contient des lignes vides, toutes les lignes vides sauf une seront supprimées.

Comment puis-je conserver toutes les lignes vides tout en supprimant toutes les lignes en double non vides, en utilisant uniquement awk? Veuillez également inclure une brève explication.

Serge Stroobandt
la source

Réponses:

28

Une autre option consiste à vérifier NF, par exemple:

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

Alternativement

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

L'astuce principale est la même, seen[$0]++crée une entrée dans le seentableau associatif dont la clé est la ligne courante ( $0). Par conséquent, !seen[$0]++sera faux si cette ligne a déjà été vue. Le /./vérifie si la ligne contient des caractères non vides, donc !/./correspond aux lignes non vides. Combiné avec lui, || !seen[$0]++il ignorera toutes les lignes en double sauf les lignes vides et imprimera le reste.

terdon
la source
Je pense que cela aurait dû être la réponse acceptée. +1 pour explication!
SS Anne
5
awk '/^[[:blank:]]*$/ { print; next; }; !seen[$0]++'

Tout ce que vous avez à faire est de vérifier d'abord une ligne vide (vraiment vide ou juste vide).

Hauke ​​Laging
la source
5

Voici une autre awksolution, similaire à la réponse de @ Thor, moins concise mais plus efficace:

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

Avec cela, nous vérifions seulement qu'il a[$0]existe ou non. Sinon, initialisez-le puis imprimez. Dans ce cas, nous n'avons aucune référence, affectation à a[$0]si elle existait.

cuonglm
la source
Je n'ai pas mesuré de différence de temps significative avec mon fichier de test de 288 lignes. Cependant, votre code attrape certainement le prix pour être le plus lisible.
Serge Stroobandt