Dieser Einzeiler entfernt doppelte Zeilen aus der Texteingabe ohne Vorsortierung.
Beispielsweise:
$ cat >f
q
w
e
w
r
$ awk '!a[$0]++' <f
q
w
e
r
$
Der Originalcode, den ich auf den Internets gefunden habe, lautete:
awk '!_[$0]++'
Dies war für mich noch verwirrender, als ich _
eine besondere Bedeutung in awk annahm, wie in Perl, aber es stellte sich heraus, dass es sich nur um den Namen eines Arrays handelte.
Jetzt verstehe ich die Logik hinter dem Einzeiler : Jede Eingabezeile wird als Schlüssel in einem Hash-Array verwendet, daher enthält der Hash nach Fertigstellung eindeutige Zeilen in der Reihenfolge des Eintreffens.
Was ich lernen möchte, ist, wie genau diese Notation von awk interpretiert wird. ZB was das Bang-Zeichen ( !
) bedeutet und die anderen Elemente dieses Code-Snippets.
Wie funktioniert es?
Antworten:
Wir werden sehen,
zuerst
Wir betrachten den Wert von
a[$0]
(Arraya
mit der ganzen Eingabezeile ($0
) als Schlüssel).Wenn es nicht existiert (
!
Negation im Test wird zu true ausgewertet)Wir drucken die Eingabezeile
$0
(Standardaktion).Außerdem fügen wir one (
++
) hinzua[$0]
, damit beim nächsten Mal!a[$0]
false ausgewertet wird.Schön zu finden !! Sie sollten sich Codegolf ansehen!
quelle
awk
als Test für jede Eingabezeile verwendet. Bei jedem erfolgreichen Testawk
wird die Aktion in geschweiften Klammern ausgeführt, die weggelassen werden{print}
. Vielen Dank!awk
, ist die Standardaktion{print $0}
. Dies bedeutet, dass alles, was als wahr bewertet wird, dies standardmäßig ausführt. So werden zum Beispielawk '1' file
alle Zeilenawk '$1' file
gedruckt, alle Zeilen, deren erstes Feld nicht leer oder 0 ist, usw.Hier ist die Bearbeitung:
a[$0]
: Schauen Sie sich den Wert des Schlüssels$0
im assoziativen Array ana
. Wenn es nicht vorhanden ist, erstellen Sie es.a[$0]++
: Inkrementiere den Wert vona[$0]
, gib den alten Wert als Ausdruckswert zurück. Ista[$0]
dies nicht der Fall, kehren Sie zurück0
und erhöhen Siea[$0]
den Wert auf1
(++
Operator gibt numerischen Wert zurück).!a[$0]++
: negiere den Wert des Ausdrucks. Beia[$0]++
return0
wird der gesamte Ausdruck als true ausgewertet. Führen Sieawk
eine Standardaktion ausprint $0
. Andernfalls wird der gesamte Ausdruck als falsch ausgewertet, und die Ursachenawk
tun nichts.Verweise:
Mit
gawk
können wir dgawk (oder eineawk --debug
neuere Version) verwenden , um eingawk
Skript zu debuggen . Erstellen Sie zunächst eingawk
Skript mit dem Namentest.awk
:Dann renne:
oder:
In der Debugger-Konsole:
Sie sehen,
Op_postincrement
wurde vorher ausgeführtOp_not
.Sie können auch
si
oderstepi
anstelle vons
oder verwendenstep
, um Folgendes deutlicher zu sehen:quelle
!
angewendet wurde++
.!
Operators berechnet wurde. Sie verwechseln die Priorität eines Operators (!a[$0]++
wird wie folgt analysiert!(a[$0]++)
) mit der Reihenfolge der Auswertung (die Zuweisung des neuen Werts vona[$0]
erfolgt, nachdem der Wert des Ausdrucks berechnet wurde).!x
berechnet, wobeix
der alte Wert von ista[$0]
. Danna[$0]
steht auf1+x
.