Esse alinhamento remove linhas duplicadas da entrada de texto sem pré-classificação.
Por exemplo:
$ cat >f
q
w
e
w
r
$ awk '!a[$0]++' <f
q
w
e
r
$
O código original que encontrei nas internets dizia:
awk '!_[$0]++'
Isso foi ainda mais desconcertante para mim, pois eu _
tive um significado especial no awk, como no Perl, mas acabou sendo apenas o nome de uma matriz.
Agora, eu entendo a lógica por trás da linha única: cada linha de entrada é usada como chave em uma matriz de hash; assim, após a conclusão, o hash contém linhas únicas na ordem de chegada.
O que eu gostaria de aprender é como exatamente essa notação é interpretada pelo awk. Por exemplo, o que significa o sinal de estrondo ( !
) e os outros elementos desse trecho de código.
Como funciona?
Respostas:
Vamos ver,
primeiro
olhamos o valor de
a[$0]
(arraya
com toda a linha de entrada ($0
) como chave).Se não existir (a
!
negação no teste será avaliada como verdadeira)imprimimos a linha de entrada
$0
(ação padrão).Além disso, adicionamos um (
++
) aa[$0]
, para que da próxima vez o valor!a[$0]
seja falso.Bom, encontre !! Você deve dar uma olhada no código de golfe!
fonte
awk
como teste para cada linha de entrada; toda vez que o teste éawk
executado com êxito, a ação é feita com chaves, o que, quando omitido, é{print}
. Obrigado!awk
, a ação padrão é{print $0}
. Isso significa que qualquer coisa avaliada como verdadeira executará isso como padrão. Assim, por exemploawk '1' file
imprime todas as linhas,awk '$1' file
imprime todas as linhas cujo primeiro campo não está vazio ou 0, etc.Aqui está o processamento:
a[$0]
: observe o valor da chave$0
, no array associativoa
. Se não existir, crie-o.a[$0]++
: incrementa o valor dea[$0]
, retorna o valor antigo como valor da expressão. Sea[$0]
não existir, retorne0
e aumentea[$0]
para1
(o++
operador retorna valor numérico).!a[$0]++
: nega o valor da expressão. Sea[$0]++
retornar0
, toda a expressão será avaliada como verdadeira, faça aawk
ação padrão executadaprint $0
. Caso contrário, toda a expressão é avaliada como falsa, as causasawk
não fazem nada.Referências:
Com
gawk
, podemos usar o dgawk (ouawk --debug
com a versão mais recente) para depurar umgawk
script. Primeiro, crie umgawk
script chamadotest.awk
:Então corra:
ou:
No console do depurador:
Você pode ver,
Op_postincrement
foi executado antesOp_not
.Você também pode usar
si
ou emstepi
vez des
oustep
para ver com mais clareza:fonte
!
é aplicada antes++
.!
operador é calculado. Você está confundindo a precedência do operador (!a[$0]++
é analisada como!(a[$0]++)
) com a ordem de avaliação (a atribuição do novo valor dea[$0]
acontece após o cálculo do valor da expressão).!x
é calculado, ondex
está o valor antigo dea[$0]
. Entãoa[$0]
está definido como1+x
.