BEGIN und ENDE mit dem Befehl awk

12

Laut dem awk-Handbuch werden BEGIN und END nicht verwendet, um Eingaben abzugleichen, sondern um dem awk-Skript Start- und Bereinigungsinformationen bereitzustellen. Hier ist das gegebene Beispiel:

ls -l | \
awk 'BEGIN { print "Files found:\n" } /\<[a|x].*\.conf$/ { print $9 }'
Files found:
amd.conf
antivir.conf
xcdroast.conf
xinetd.conf

Zuerst wird eine Zeichenfolge gedruckt, die ausgegeben werden soll. Anschließend wird die Eingabe auf eine Musterübereinstimmung überprüft, wobei die Eingabe mit einem oder x beginnt, gefolgt von einem oder mehreren Zeichen, gefolgt von der .conf. Für alle Übereinstimmungen wird die 9. Spalte gedruckt.

Die Tatsache, dass wir gezwungen sind, hier zu beginnen, bedeutet, dass awk höchstens eine Druckfunktion verwenden kann, die BEGIN oder END enthält? Wenn nicht, warum können wir dann nicht einfach die Druckfunktion am Anfang ohne das Schlüsselwort BEGIN verwenden? Es scheint, dass der BEGIN überflüssig ist.

John Merlino
quelle
Wenn Sie den Befehl einfach ohne BEGIN ausführen, wird Ihre Frage beantwortet und es wird angezeigt, dass dies nicht überflüssig ist und Sie ein anderes Ergebnis erhalten.
MSB

Antworten:

10

Das BEGINist nicht überflüssig. Wenn Sie nicht angeben, BEGINwird das printfür jede Eingabezeile ausgeführt.

Zitat aus dem Handbuch :

Eine BEGINRegel wird nur einmal ausgeführt, bevor der erste Eingabedatensatz gelesen wird. Ebenso wird eine ENDRegel nur einmal ausgeführt, nachdem alle Eingaben gelesen wurden.

$ seq 5 | awk 'BEGIN{print "Hello"}/4/{print}'   # Hello printed once
Hello
4
$ seq 5 | awk '{print "Hello"}/4/{print}'        # Hello printed for each line of input
Hello
Hello
Hello
Hello
4
Hello
$
devnull
quelle
7

awkverarbeitet jede Eingabezeile für die im Text angegebenen Ausdrücke außer BEGINund END-Blöcken. Im Fall von BEGINund ENDBlöcken awkwerden die Anweisungen nur einmal verarbeitet, bevor die Verarbeitung der Eingabe begonnen hat bzw. nachdem die Verarbeitung der Eingabe abgeschlossen wurde. Ohne den BEGINBlock wären Sie nicht nur nicht in der Lage, einmalige Informationen wie Überschriften zu drucken, sondern könnten auch einige der vom Körper benötigten Variablen nicht effizient initialisieren. Auch FYI, ein awkProgramm kann mehrere haben BEGINund ENDBlöcke.

mkc
quelle
2

awkführt jeden Block nur aus, wenn das Muster davor übereinstimmt. Das leere Muster (nur Block) entspricht jeder Zeile. BEGINund ENDsind spezielle Muster, die dem Anfang und dem Ende der Datei entsprechen (analog zur Bedeutung von ^und $in horizontaler Richtung).

Wenn Sie vor dem Lesen der Datei etwas ausführen möchten, verwenden Sie BEGIN. Zum Beispiel die Initialisierung von Zählern oder so. ENDkönnte dann die Ergebnisse sammeln.

Orion
quelle
0

In dem Beispiel, das meiner Meinung nach aus pädagogischen Gründen vereinfacht ist, haben Sie Recht, dass es überflüssig ist. Sie könnten die gleichen Ergebnisse erhalten, ohne zu verwenden BEGIN.

1 == NR            { print "Files found:\n" }
/\<[a|x].*\.conf$/ { print $9               }

würde die gleichen Ergebnisse liefern, da die print-Anweisung nur auf die erste Eingabezeile beschränkt ist.

Davon abgesehen sind die BEGINund END-Blöcke unglaublich leistungsfähige Werkzeuge. Wie bereits erwähnt, können Sie mit dem BEGINBlock Variablen oder andere Routinen initialisieren, die nur einmal ausgeführt werden müssen. Sie können jedoch auch Awk-Befehle ausführen, wenn keine zu verarbeitenden Dateien vorhanden sind. Ein einfaches Beispiel:

BEGIN { print sqrt(12/4) }

Sie können hier ein ernsthafteres Beispiel für die Programmierung in Awk sehen, ohne Eingaben zu verarbeiten .

Ebenso ist der ENDBlock äußerst nützlich, um Berechnungen durchzuführen und alle Eingaben zusammenzufassen. Dies kann (normalerweise) nicht ohne vorheriges Einlesen aller Daten erfolgen. Ein einfaches Beispiel für die Zusammenfassung von Eingaben finden Sie hier

myq
quelle