Warum druckt awk diese Zeile mehr als einmal?

Warum druckt awk diese Zeile mehr als einmal?

Ich habe folgendes LDIF:

dn: cn=Robert Smith,ou=people,dc=example,dc=com
objectclass: inetOrgPerson
cn: Robert Smith
cn: Robert J Smith
cn: bob  smith
sn: smith
uid: rjsmith
userpassword: rJsmitH
carlicense: HISCAR 123
homephone: 555-111-2222
mail: [email protected]
alias: [email protected]
alias: [email protected]
description: nice hair
ou: Human Resources

dn: cn=John Doe,ou=people,dc=example,dc=com
objectclass: inetOrgPerson
cn: John Doe
cn: John Walker Doe
cn: Johnny
sn: Doe
uid: jdoe
userpassword: topsecret
carlicense: AKAHH 123
homephone: 123-458-362
mail: [email protected]
alias: [email protected]
alias: [email protected]
description: cool guy
ou: Sales

Jetzt führe ich einen Awk-Befehl dagegen aus:

awk '/^mail:/ { mail = $2 }; {print mail };' ldif

Das erwartete Ergebnis wäre:

[email protected]
[email protected]

Das tatsächliche Ergebnis ist:

[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]

Ich verstehe nicht wirklich, warum awk diese Ausgabe mehrfach ausgibt. Ich wäre sehr dankbar, wenn mir das jemand erklären könnte, da ich neu bei awk bin und es bisher nicht viel verwendet habe. Ich habe bereits die Manpage und Google konsultiert, aber ich glaube, ich suche dort nach den falschen Dingen ...

EDIT: Ich verstehe, dass awk Textströme zeilenweise verarbeitet. Ich schätze, mein „print“ druckt die Ausgabe einfach so oft aus, wie meine ldif-Datei Zeilen enthält. Aber wie kann ich awk daran hindern? Ich möchte jedes Ergebnis nur einmal drucken.

Antwort1

Die Bedingung /^mail:/betrifft nicht alle folgenden Anweisungen, sondern nur die erste ( mail = $2).

Als Ergebnis print mailwird die zweite Anweisung () ausgeführtfür jede Zeile.

Aus diesem Grund stehen am Anfang der Ausgabe tatsächlich einige Leerzeilen ( mailist noch nicht festgelegt).

Alle davon funktionieren:

awk '/^mail:/ { { mail=$2 }; {print mail } };' ldif

awk '/^mail:/ { mail=$2; print mail };' ldif

Persönlich würde ich Folgendes bevorzugen:

awk '/^mail:/ { print $2 }' ldif

Antwort2

@Dennis hat eine Lösung mit der richtigen Syntax angeboten, aber die ursprüngliche Frage „Warum druckt awk diese Zeile mehr als einmal?“ nicht vollständig beantwortet.

Awk läuft in einer zeilenorientierten Schleife und führt mit geringfügigen Ausnahmen (z. B. BEGIN und END) das gesamte Skript für jede Eingabezeile aus. Im Beispiel des OP wurde der folgende Pseudocode für jede Zeile der Eingabedatei ausgeführt:

if LINE starts with "mail:"
    set MAIL to value of second field of the input record
endif

print MAIL

Der Grund für die doppelten Ausgabezeilen liegt darin, dass die Druckanweisungdraußendie bedingte Anweisung und wird daher ausgeführt fürjedenEingabezeile, statt nur Zeilen, die dem regulären Ausdruck entsprechen. Da die mailVariable außerdem nur innerhalb der bedingten Anweisung gesetzt wird, wird der alte Wert immer wieder verwendet, bis das nächste Mal eine Eingabezeile mit der bedingten Anweisung übereinstimmt.

verwandte Informationen