Como remover linhas duplicadas com o awk, mantendo linhas vazias?

13

O awkcomando abaixo remove todas as linhas duplicadas, conforme explicado aqui :

awk '!seen[$0]++'

Se o texto contiver linhas vazias, todas, exceto uma linha vazia, serão excluídas.

Como posso manter todas as linhas vazias enquanto excluo todas as linhas duplicadas não vazias, usando apenas awk? Por favor, inclua também uma breve explicação.

Serge Stroobandt
fonte

Respostas:

28

Outra opção é verificar NF, por exemplo:

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

alternativamente

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

O truque principal é o mesmo, seen[$0]++cria uma entrada na seenmatriz associativa cuja chave é a linha atual ( $0). Portanto, !seen[$0]++será falso se essa linha já tiver sido vista. Ele /./está verificando se a linha contém caracteres não em branco, portanto, !/./corresponde a linhas não em branco. Combinado com || !seen[$0]++ele, todas as linhas duplicadas, exceto as em branco, ignoram e imprimem o restante.

Terdon
fonte
Eu acho que essa deveria ter sido a resposta aceita. +1 para explicação!
SS Anne
5
awk '/^[[:blank:]]*$/ { print; next; }; !seen[$0]++'

Tudo o que você precisa fazer é procurar uma linha vazia (realmente vazia ou apenas em branco) primeiro.

Hauke ​​Laging
fonte
5

Aqui está outra awksolução, semelhante à resposta de @ Thor, menos concisa, mas mais eficiente:

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

Com isso, apenas verificamos a[$0]se existe ou não. Caso contrário, inicialize-o e imprima. Nesse caso, não temos nenhuma referência, atribuição, a[$0]se ela existia.

cuonglm
fonte
Não medi nenhuma diferença de tempo significativa com meu arquivo de teste de 288 linhas. No entanto, seu código certamente recebe o prêmio por ser o mais legível.
Serge Stroobandt