Cette doublure supprime des lignes en double à partir de la saisie de texte sans pré-tri.
Par exemple:
$ cat >f
q
w
e
w
r
$ awk '!a[$0]++' <f
q
w
e
r
$
Le code d'origine que j'ai trouvé sur les internets a lu:
awk '!_[$0]++'
C'était encore plus perplexe pour moi alors que j'ai pris _
Pour avoir une signification particulière dans Awk, comme dans Perl, mais il s'est avéré être juste un nom d'une matrice.
Maintenant, je comprends la logique derrière la ligne one-liner: Chaque ligne d'entrée est utilisée comme une clé dans une matrice de hachage. Ainsi, à la fin, le hachage contient des lignes uniques dans l'ordre d'arrivée.
Ce que j'aimerais apprendre, c'est comment exactement cette notation est interprétée par Awk. Par exemple. Quel signe de bang (!
) signifie et les autres éléments de cet extrait de code.
Comment ça marche?
Voyons,
!a[$0]++
premier
a[$0]
nous examinons la valeur de a[$0]
(Array a
avec une ligne d'entrée entière ($0
) comme clé).
Si cela n'existe pas (!
Est-ce que la négation dans le test sera évaluée à la vraie)
!a[$0]
nous imprimons la ligne d'entrée $0
(action par défaut).
En outre, nous en ajoutons un (++
) à a[$0]
, Alors la prochaine fois !a[$0]
évaluera à faux.
Nice, trouver !! Vous devriez avoir un coup d'œil au code golf!
Voici le traitement:
a[$0]
: regardez la valeur de la clé $0
, dans le tableau associatif a
. Si cela n'existe pas, créez-le.
a[$0]++
: incrément la valeur de a[$0]
, renvoie l'ancienne valeur comme valeur de l'expression. Si a[$0]
n'existe pas, retour 0
et incrément a[$0]
à 1
(++
opérateur renvoie la valeur numérique).
!a[$0]++
: nier la valeur de l'expression. Si a[$0]++
revenir 0
, l'ensemble de l'expression est évalué à vrai, faire awk
action par défaut print $0
. Sinon, toute l'expression est évaluée à FALSE, causes awk
ne rien faire.
Les références:
Avec gawk
, nous pouvons utiliser dgawk (ou awk --debug
avec la version plus récente) Pour déboguer un script gawk
. Tout d'abord, créez un script gawk
, nommé test.awk
:
BEGIN {
a = 0;
!a++;
}
Puis exécutez:
dgawk -f test.awk
ou:
gawk --debug -f test.awk
Dans la console de débogueur:
$ dgawk -f test.awk
dgawk> trace on
dgawk> watch a
Watchpoint 1: a
dgawk> run
Starting program:
[ 1:0x7fe59154cfe0] Op_rule : [in_rule = BEGIN] [source_file = test.awk]
[ 2:0x7fe59154bf80] Op_Push_i : 0 [PERM|NUMCUR|NUMBER]
[ 2:0x7fe59154bf20] Op_store_var : a [do_reference = FALSE]
[ 3:0x7fe59154bf60] Op_Push_lhs : a [do_reference = TRUE]
Stopping in BEGIN ...
Watchpoint 1: a
Old value: untyped variable
New value: 0
main() at `test.awk':3
3 !a++;
dgawk> step
[ 3:0x7fe59154bfc0] Op_postincrement :
[ 3:0x7fe59154bf40] Op_not :
Watchpoint 1: a
Old value: 0
New value: 1
main() at `test.awk':3
3 !a++;
dgawk>
Tu peux voir, Op_postincrement
a été exécuté avant Op_not
.
Vous pouvez également utiliser si
ou stepi
_ au lieu de s
ou step
pour voir plus clairement:
dgawk> si
[ 3:0x7ff061ac1fc0] Op_postincrement :
3 !a++;
dgawk> si
[ 3:0x7ff061ac1f40] Op_not :
Watchpoint 1: a
Old value: 0
New value: 1
main() at `test.awk':3
3 !a++;