awk/Einstieg in awk

Aus Mikiwiki
< awk
Version vom 11. August 2011, 12:34 Uhr von Michi (Diskussion | Beiträge) (→‎Einige Beispiele)
(Unterschied) ← Nächstältere Version | Aktuelle Version (Unterschied) | Nächstjüngere Version → (Unterschied)
Zur Navigation springen Zur Suche springen

Ausführen eines awk-Programms

Es gibt mehrere Möglichkeiten, awk über die Befehlszeile aufzurufen:

  • Aufruf des Programms ohne Eingabedatei
  • Aufruf des Programms mit Eingabedatei
  • Aufruf einer Programmdatei mit Eingabedatei

Aufruf des Programms ohne Eingabedatei

awk kann ganz ohne Eingabedatei aufgerufen werden, wobei das Programm dann solange auf die Standardeingabe angewendet wird, bis durch "CTRL+D" das Dateiende angezeigt wird.

awk 'program'

Beispiele

$ awk "BEGIN { print \"Don't panic\" }"
Don't panic

$ awk '{ print }'
Das ist ein Beispiel.
Das ist ein Beispiel.
CTRL+D

Aufruf des Programms mit Eingabedatei

Kurze Programme können von awk direkt über die Befehlszeile ausgeführt werden, wobei das Programm aus einzelnen Mustern und Aktionen besteht. Um das Programm werden einfache Anführungszeichen gesetzt, damit die Shell keine awk-Zeichen als spezielle Shellzeichen interpretiert. Die einfachen Anführunszeichen bewegen die Shell auch dazu, das ganze Programm als ein einzelnes Argument anzusehen, sodass das Programm länger als eine Zeile sein kann.

awk 'program' inputfile1 inputfile2 ...

Aufruf einer Programmdatei mit Eingabedatei

Längere Programme werden besser in eine Datei geschrieben und in dieser Art von awk über die Befehlszeile ausgeführt.

awk -f programfile inputfile1 inputfile2 ...

Beispiel

$ vi advice.awk
BEGIN { print "Don't panic!" }
$ awk -f advice.awk
Don't panic!

Der awk-Befehl kann auch direkt in eine ausführbare Datei geschrieben werden.

$ vi advice.awk
#!/usr/bin/awk -f
# Kommentarzeile, die in der Ausgabe nicht angezeigt wird
BEGIN { print "Don't panic!" }
$ chmod 744 advice.awk
$ ./advice.awk
Don't panic!

Quoting

Einfache und doppelte Anführungszeichen zu mischen ist schwierig. Es bleibt nichts anderes, als gewisse Tricks anzuwenden. Das folgende Beispiel besteht aus drei verknüpften Zeichenketten: die erste und die dritte arbeiten mit einfachen, die zweite mit doppelten Anführungszeichen.

$ awk 'BEGIN { print "Ein einfaches Anführungszeichen: <'"'"'>" }'
Ein einfaches Anführungszeichen: <'>

Diese Schreibweise kann vereinfacht werden zu:

$ awk 'BEGIN { print "Ein einfaches Anführungszeichen: <'\''>" }'
Ein einfaches Anführungszeichen: <'>

Eine weitere Möglichkeit ist es, die eingebetteten doppelten Anführungszeichen zu fluchten:

$ awk "BEGIN { print \"Ein einfaches Anführungszeichen: <'>\" }"
Ein einfaches Anführungszeichen: <'>

Wenn wirklich sowohl einfache wie doppelte Anführungszeichen verwendet werden müssen, ist es am einfachsten, die Befehle in eine eigene Datei zu schreiben, wo die Shell nicht mitinterpretiert.

Einige Beispiele

Suche in der Datei "bbslist" nach der Zeichenkette "foo". Dabei wird der reguläre Ausdruck "/foo/" verwendet, der das Muster "foo" enthält. Ausgegeben ("print") wird jeweils die aktuelle Zeile ("$0") - da "print" ohne Zusatz immer die aktuelle Zeile ausgibt, könnte hier der Zusatz "$0" auch weggelassen werden.

$ awk '/foo/ { print $0 }' bbslist
fooey        555-1234     2400/1200/300     B
foot         555-6699     1200/300          B
macfoo       555-6480     1200/300          A
sabafoo      555-2127     1200/300          C

In einer awk-Regel können entweder das Muster oder die Aktion weggelassen werden, aber nicht beide. Wird das Muster weggelassen, so wird die Aktion für alle Eingabezeilen ausgeführt. Wird die Aktion weggelassen, so werden standardmässig alle Zeilen ausgegeben, auf die das Muster passt.

Ausgabe der Länge der längsten Eingabezeile der Datei "file".

awk '{ if (length($0) > max) max = length($0) }
     END { print max }' file

Ausgabe jeder Zeile der Datei "file", die länger ist als 80 Zeichen. Als Muster wird hier ein regulärer Ausdruck verwendet; da kein keine Aktion angegeben wurde, wird die Standardaktion angewendet: das Ausgeben der Zeile.

awk 'length($0) > 80' file

Ausgabe der Länge der längsten Zeile der Datei "file". Die Eingabedatei wird vom Programm expand verarbeitet, um Tabulatoren in Leerschläge umzuwandeln.

expand file | awk '{ if (x < length()) x = length() }
                   END { print "Die grösste Zeilenlänge ist " x }'

Ausgabe aller Zeilen der Datei "file", die mindestens ein Feld enthalten. So können beispielsweise Leerzeilen aus einer Datei entfernt werden.

awk 'NF > 0' file

Ausgabe von sieben zufälligen Zahlen zwischen 0 und einschliesslich 100.

awk 'BEGIN { for (i = 1; i <= 7; i++)
                 print int(101 * rand()) }'

Ausgabe der Anzahl Byte in den Dateien "bbslist" und "inventoryshipped".

ls -l bbslist inventoryshipped | awk '{ x+= $5 } ; END {print "Total byte: " x }'

Ausgabe der Anzahl Kilobyte in den Dateien "bbslist" und "inventoryshipped".

ls -l bbslist inventoryshipped | awk '{ x+= $5 }
                                      END {print "Total K-byte: " x/1024 }'

Ausgabe einer Liste mit den Loginnamen aller Benutzer, wobei die Loginnamen erst ab dem dritten Zeichen ausgegeben werden.

awk -F: '{ print substr($1,3) }' /etc/passwd

Zählen der Zeilen ind der Datei "file".

awk 'END { print NR }' file

Ausgabe der Zeilen mit gerader Zeilennummer in der Datei "file".

awk 'NR % 2 == 0' file

Ausgabe der Zeilen mit ungerader Zeilennummer in der Datei "file".

awk 'NR % 2 == 1' file

Beispiel mit zwei Regeln

awk liest aus den Eingabedateien jeweils eine Zeile und versucht darauf die Muster jeder Regel anzuwenden. Wenn mehrere Muster passen, so werden mehrere Aktionen gemäss der Reihenfolge wie sie im awk-Programm erscheinen ausgeführt. Passt kein Muster, so werden keine Aktionen ausgeführt.

Nachdem alle Regeln die auf die Zeile passen ausgeführt wurden (also vielleicht auch keine), liest awk die nächste Zeile. Das geschieht solange, bis awk das Dateiende erreicht.

Das folgende Beispiel hat zwei Regeln. Die erste Regel hat die Zeichenkette "12" als Muster und "print $0" als Aktion. Die zweite Regel hat die Zeichenkette "21" als Muster und "print $0" als Aktion. Die Aktion jeder Regel ist in ihre eigenen Klammern eingeschlossen. Das Programm gibt jede Zeile aus, welche die Zeichenkette "12" oder "21" enthält. Falls eine Zeile beide Zeichenketten enthält, wird sie zweimal ausgegeben, je einmal von jeder Regel.

$ awk '/12/ { print $0 }
       /21/ { print $0 }' bbslist
aardvark     555-5553     1200/300          B
alpo-net     555-3412     2400/1200/300     A
barfly       555-7685     1200/300          A
bites        555-1675     2400/1200/300     A
core         555-2912     1200/300          C
fooey        555-1234     2400/1200/300     B
foot         555-6699     1200/300          B
macfoo       555-6480     1200/300          A
sdace        555-3430     2400/1200/300     A
sabafoo      555-2127     1200/300          C
sabafoo      555-2127     1200/300          C

Das Programm könnte aus Gründen der Platzersparnis auch wie folgt geschrieben werden:

$ awk '/12/ { print $0 } ; /21/ { print $0 }' bbslist

Ein komplexeres Beispiel

Das folgende Beispiel zeigt, wie awk verwendet werden kann, um die Ausgabe eines anderen Programms zusammenzufassen, auszuwählen und neu zu ordnen.

Das Programm gibt die totale Anzahl Byte aller Dateien im aktuellen Verzeichnis aus, die zuletzt am 30. Oktober 2007 verändert wurden. Jedes Mal, wenn eine Zeile die Zeichenkette "2007-10-30" als sechstes Feld hat ("$6"), wird die Aktion "sum += $5" ausgeführt, also das fünfte Feld der Ausgabe von "ls -l" zur Variable "sum" hinzugefügt. Nach Verarbeitung der letzten Ausgabezeile von "ls -l" wird die Regel "END" ausgeführt und der Wert der Variable "sum" ausgegeben.

$ ls -l | awk '$6 == "2007-10-30" { sum += $5 }
               END { print sum }'

awk Anweisungen und Zeilen

Normalerweise ist jede Zeile eines awk-Programms eine eigene Anweisung oder Regel. Allerdings ignoriert gawk Zeilenschaltungen (newlines) nach jedem der folgenden Zeichen und Schlüsselworte:

,     {     ?     :     ||     &&     do     else

Soll eine einzelne Anweisung an einer Stelle fortgesetzt werden, an der eine Zeilenschaltung sie beenden würde, kann sie stattdessen durch Setzen eines umgekehrten Schrägstrichs ("\") fortgesetzt werden. Der umgekehrte Schrägstrich ist an jeder Stelle der Anweisung erlaubt, sogar mitten in einer Zeichenkette oder einem regulären Ausdruck (davon ist allerdings abzuraten). Er muss dafür allerdings zwingend als letztes Zeichen der Zeile stehen.

$ awk '/Dieser reguläre Ausdruck ist zu lang, setze ihn \
  darum auf der nächsten Zeile fort/ { print $1 }'

In gawk gibt es keine Begrenzung der Zeilenlänge, sodass dieses Vorgehen niemals zwingend notwendig ist. Aus Lesbarkeitsgründen kann es dennoch z. B. beim Schreiben von Programmdateien verwendet werden.

awk ist eine zeilenorientierte Programmiersprache. Die Aktion jeder Regel muss auf derselben Zeile beginnen wie das zugehörige Muster. Um Muster und Aktion auf zwei verschiendenen Zeilen anzuzeigen muss zwingend der umgekehrte Schrägstrich verwendet werden.