13.4 Muster (bzw. Adressen) von awk-Scripts
Wie schon bei sed können Sie mit awk Adressen bzw. Muster benennen, die als Suchkriterium angegeben werden. Ein Muster dient auch hier dazu, den Programmfluss von awk zu steuern. Stimmt der Inhalt mit der zu bearbeitenden Zeile mit dem angegebenen Muster überein, wird der entsprechende Aktionsteil ausgeführt. Um solche Muster in awk darzustellen, haben Sie mehrere Möglichkeiten. Welche dies sind und wie Sie diese verwenden können, erfahren Sie in den folgenden Unterabschnitten.
13.4.1 Zeichenkettenvergleiche
Am einfachsten und gleichzeitig auch häufigsten werden Muster bei Zeichenvergleichen eingesetzt. Diese Verwendung sieht folgendermaßen aus:
you@host > awk '/Jürgen Wolf/'
Hallo Jürgen
Hallo Wolf
Mein Name ist Jürgen Wolf
Mein Name ist Jürgen Wolf
(Strg)+(D)
Hier wird nur die Eingabe von der Tastatur wiederholt, wenn in $0 die Textfolge »Jürgen Wolf« enthalten ist. Auf eine Datei wird der Zeichenkettenvergleich ähnlich ausgeführt:
you@host > awk '/Samir/' mrolympia.dat
Samir Bannout Libanon 1983
Hier erhält awk die Eingabezeile aus der Datei mrolympia.dat, sucht nach einem Muster und gibt gegebenenfalls die komplette Zeile der Fundstelle auf den Bildschirm aus. Hier fällt außerdem auf, dass awk auch ohne den Aktionsteil und den Befehl print die komplette Zeile auf dem Bildschirm ausgibt. Natürlich werden auch Teil-Textfolgen gefunden, sprich es müssen nicht zwangsläufig ganze Wörter sein:
you@host > awk '/ie/' mrolympia.dat
Franco Columbu Argentinien 1976 1981
Dorian Yates Grossbritannien 1992 1993 1994 1995 1996 1997
Ronnie Coleman USA 1998 1999 2000 2001 2002 2003 2004
13.4.2 Vergleichsausdrücke
awk bietet auch Vergleichsausdrücke in den Mustern an. Hierzu werden die in vielen Programmiersprachen üblichen Vergleichsoperatoren verwendet. Ist ein Vergleichsausdruck (also das Muster) wahr, wird der entsprechende Aktionsteil ausgeführt. In der folgenden Tabelle finden Sie alle Vergleichsoperatoren aufgelistet.
Tabelle 13.3
Vergleichsoperatoren von awk
Operator
|
Bedeutung
|
Beispiel
|
<
|
Kleiner als
|
x < y
|
<=
|
Kleiner als oder gleich
|
x <= y
|
==
|
Gleichheit
|
x == y
|
!=
|
Ungleichheit
|
x != y
|
>=
|
Größer als oder gleich
|
x >= y
|
>
|
Größer als
|
x > y
|
~
|
Mustervergleich
|
x ~ /y/
|
!~
|
Negierter Mustervergleich
|
x !~ /y/
|
Ein Vergleichsausdruck lässt sich dabei sowohl auf Zahlen als auch auf Zeichenketten anwenden. Ein Beispiel:
you@host > awk '$4 > 1990' mrolympia.dat
Dorian Yates Grossbritannien 1992 1993 1994 1995 1996 1997
Ronnie Coleman USA 1998 1999 2000 2001 2002 2003 2004
Hier geben Sie alle Teilnehmer aus, die Ihren ersten Wettkampf nach 1990 gewonnen haben. Es werden also sämtliche Zeilen ausgegeben, bei denen der Wert des vierten Feldes größer als 1990 ist. Ein weiteres Beispiel:
you@host > awk '$2 < "H"' mrolympia.dat
Franco Columbu Argentinien 1976 1981
Chris Dickerson USA 1982
Samir Bannout Libanon 1983
Ronnie Coleman USA 1998 1999 2000 2001 2002 2003 2004
Hiermit werden alle Werte (Namen) der zweiten Spalte ausgegeben, deren Anfangsbuchstabe kleiner als »H« ist. Gemeint ist hier der ASCII-Wert! »C« ist zum Beispiel kleiner als »H« in der ASCII-Tabelle usw. Natürlich lässt sich dies auch auf eine ganze Zeichenkette anwenden:
you@host > awk '$1 > "Dorian" ' mrolympia.dat
Larry Scott USA 1965 1966
Sergio Oliva USA 1967 1968 1969
Franco Columbu Argentinien 1976 1981
Samir Bannout Libanon 1983
Lee Haney USA 1984 1985 1986 1987 1988 1989 1990 1991
Ronnie Coleman USA 1998 1999 2000 2001 2002 2003 2004
Hier werden alle Vornamen ausgegeben, deren Name im ersten Feld größer als (heißt: nicht länger) der von »Dorian« ist – auch wenn es in diesem Beispiel wenig Sinn macht. Interessant ist auch der Vergleichsoperator für Mustervergleiche, beispielsweise:
you@host > awk '$3 ~ /USA/ ' mrolympia.dat
Larry Scott USA 1965 1966
Sergio Oliva USA 1967 1968 1969
Chris Dickerson USA 1982
Lee Haney USA 1984 1985 1986 1987 1988 1989 1990 1991
Ronnie Coleman USA 1998 1999 2000 2001 2002 2003 2004
Hier werden alle Zeilen selektiert, in denen sich in der dritten Spalte das Muster »USA« befindet. Damit können Sie das exakte Vorkommen eines Musters in der entsprechenden Spalte bestimmen. Natürlich können Sie dies auch negieren (verneinen):
you@host > awk '$3 !~ /USA/ ' mrolympia.dat
Arnold Schwarzenegger Österreich 1970 1971 1972 1973 1974 1975
Franco Columbu Argentinien 1976 1981
Samir Bannout Libanon 1983
Dorian Yates Grossbritannien 1992 1993 1994 1995 1996 1997
Jetzt werden alle Zeilen ausgegeben, bei denen sich in der dritten Spalte nicht das Muster »USA« befindet.
Wissen Sie jetzt zum Beispiel, dass 1988 ein US-Amerikaner den Wettkampf gewonnen hat, aber nicht genau welcher, formulieren Sie dies mit awk folgendermaßen:
you@host > awk '$3 ~ /USA/ && /1988/' mrolympia.dat
Lee Haney USA 1984 1985 1986 1987 1988 1989 1990 1991
Damit wählen Sie die Zeile(n) aus, bei denen sich in der dritten Spalte das Muster »USA« befindet und irgendwo in der Zeile das Jahr 1988. Hier wurde mit dem && eine logische UND-Verknüpfung vorgenommen, worauf noch in einem extra Abschnitt eingegangen wird.
Wollen Sie nur die ersten fünf Zeilen einer Datei ausgeben lassen? Nichts ist leichter als das:
you@host > awk 'NR <=5' mrolympia.dat
Larry Scott USA 1965 1966
Sergio Oliva USA 1967 1968 1969
Arnold Schwarzenegger Österreich 1970 1971 1972 1973 1974 1975
Franco Columbu Argentinien 1976 1981
Chris Dickerson USA 1982
Wenn Sie jeden Datensatz ausgeben lassen wollen, der weniger als 5 Felder enthält, dann machen Sie dies mit awk so:
you@host > awk 'NF < 5' mrolympia.dat
Chris Dickerson USA 1982
Samir Bannout Libanon 1983
13.4.3 Reguläre Ausdrücke
Natürlich stehen Ihnen auch mit awk wieder die regulären Ausdrücke zur Verfügung, mit denen Sie Ihre Muster formulieren können. Hierzu ein kurzer Überblick zu den Metazeichen und ihren Bedeutungen, die Sie für reguläre Ausdrücke mit awk heranziehen können. Da die regulären Ausdrücke ja bereits einige Mal behandelt wurden, finden Sie hier allerdings nur einen kurzen Überblick, da die meisten Zeichen auch hier ihre bereits bekannte Funktion erfüllen.
Tabelle 13.4
Metazeichen für reguläre Ausdrücke in awk
Zeichen
|
Bedeutung
|
^
|
Anfang einer Zeile oder Zeichenkette
|
$
|
Ende einer Zeile oder Zeichenkette
|
.
|
Jedes Zeichen außer einem Zeilenumbruch
|
*
|
Null, eines oder mehrere Vorkommen
|
[]
|
Ein Zeichen aus der Menge enthalten
|
[^]
|
Kein Zeichen aus der Menge enthalten
|
re1|re2
|
ODER; entweder Muster re1 oder re2 enthalten
|
re1&re2
|
UND; Muster re1 und Muster re2 enthalten
|
+
|
Eines oder mehrere Vorkommen
|
(ab)+
|
Mindestens ein Auftreten der Menge »ab«
|
?
|
Null oder einmaliges Vorkommen
|
&
|
Enthält das Suchmuster des Ersetzungsstrings
|
Auch zur Verwendung muss wohl nicht mehr allzu viel geschrieben werden, da Sie ja bereits zuhauf Beispiele in sed gesehen haben. Trotzdem hierzu einige Beispiele mit regulären Ausdrücken.
you@host > awk '/[0–9]+/ { print $0 ": eine Zahl" } \
> /[A-Za-z]+/ { print $0 ": ein Wort" }'
Hallo
Hallo: ein Wort
1234
1234: eine Zahl
Hier können Sie ermitteln, ob es sich bei der Eingabe von der Tastatur um ein Wort oder um eine Zahl handelt. Allerdings funktioniert dieses Script nur so lange, wie es in einer Umgebung eingesetzt wird, in der sich derselbe Zeichensatz befindet wie beim Entwickler. Um hier wirklich Kompatibilität zu erreichen, sollten Sie in einem solchen Fall vordefinierte Zeichenklassen verwenden (siehe Abschnitt 1.10.6, Tabelle 1.5). In der Praxis sollte diese Zeile daher folgendermaßen aussehen:
you@host > awk '/[[:digit:]]+/ { print $0 ": eine Zahl" } \
> /[[:alpha:]]+/ { print $0 ": ein Wort" }'
Im Zusammenhang mit den regulären Ausdrücken wird zudem häufig der Match-Operator (~) eingesetzt, womit Sie ermitteln, ob ein bestimmtes Feld in einer Zeile einem bestimmten Muster (regulären Ausdruck) entspricht.
you@host > awk '$1 ~ /^[A-D]/' mrolympia.dat
Arnold Schwarzenegger Österreich 1970 1971 1972 1973 1974 1975
Chris Dickerson USA 1982
Dorian Yates Grossbritannien 1992 1993 1994 1995 1996 1997
Hier werden zum Beispiel alle Zeilen ausgegeben, bei denen in der ersten Spalte der erste Buchstabe in der Zeile ein »A«, »B«, »C« oder »D« ist. Das Gegenteil erreichen Sie mit:
you@host > awk '$1 ~ /^[^A-D]/' mrolympia.dat
Larry Scott USA 1965 1966
Sergio Oliva USA 1967 1968 1969
Franco Columbu Argentinien 1976 1981
...
Hierbei lässt sich allerdings auch erkennen, dass reguläre Ausdrücke in Verbindung mit awk zum einen sehr leistungsstark sind, aber auch sehr »kryptisch« werden können. Hier zu Rezept-Zwecken einige weitere awk-Beispiele mit regulären Ausdrücken.
awk '$0 !~ /^$/' datei.dat
Damit »löschen« Sie alle leeren Zeilen in einer Datei (datei.dat) (»Löschen« trifft die Sache eigentlich nicht genau, vielmehr löscht man die Zeilen nicht in einer Datei, sondern gibt alles, was nicht leer ist, auf dem Bildschirm aus). $0 steht für die komplette Zeile und schließt alle Muster aus (!~), die eine leere Zeile enthalten. ^ steht für den Anfang und $ für das Ende einer Zeile.
Nächstes Beispiel:
you@host > awk '$2 ~ /^[CD]/ { print $3 }' mrolympia.dat
Argentinien
USA
USA
Hier suchen Sie nach allen Zeilen, bei denen sich in der zweiten Spalte ein Wort befindet, das mit den Buchstaben »C« oder »D« beginnt, und geben bei Erfolg das dritte Feld der Zeile aus.
Noch ein Beispiel:
you@host > awk '$3 ~ /Argentinien|Libanon/' mrolympia.dat
Franco Columbu Argentinien 1976 1981
Samir Bannout Libanon 1983
Hier werden alle Zeilen ausgegeben, die in der dritten Spalte die Textfolge »Argentinien« oder »Libanon« enthalten.
13.4.4 Zusammengesetzte Ausdrücke
Es ist ebenso möglich, mehrere Ausdrücke zu einem Ausdruck zusammenzusetzen. Hierzu werden die üblichen Verknüpfungen UND (&&) und ODER (||) zwischen den Ausdrücken verwendet. So gilt bei einer UND-Verknüpfung von zwei Ausdrücken, dass der Aktionsteil bzw. der Ausdruck wahr ist, wenn beide Ausdrücke zutreffen, zum Beispiel:
you@host > awk '$3 ~ /USA/ && $2 ~ /Dickerson/' mrolympia.dat
Chris Dickerson USA 1982
Hier wird nur die Zeile ausgegeben, welche die Textfolge »USA« in der dritten Spalte als Ausdruck UND die Textfolge »Dickerson« in der zweiten Spalte enthält. Wird keine Zeile gefunden, die mit beiden Ausdrücken übereinstimmt, wird nichts ausgegeben.
Auf der anderen Seite können Sie mit einer ODER-Verknüpfung dafür sorgen, dass nur einer der Ausdrücke zutreffen muss:
you@host > awk '$3 ~ /USA/ || $2 ~ /Yates/' mrolympia.dat
Larry Scott USA 1965 1966
Sergio Oliva USA 1967 1968 1969
Chris Dickerson USA 1982
Lee Haney USA 1984 1985 1986 1987 1988 1989 1990 1991
Dorian Yates Grossbritannien 1992 1993 1994 1995 1996 1997
Ronnie Coleman USA 1998 1999 2000 2001 2002 2003 2004
Hierbei werden alle Zeilen ausgegeben, bei denen das Muster »USA« in der dritten Spalte ODER das Muster »Yates« in der zweiten Spalte enthalten ist.
Natürlich lassen sich mehr als nur zwei Ausdrücke verknüpfen und auch die ODER- bzw. UND-Verknüpfungen mischen. Doch es gilt, nicht zu übertreiben, um den Überblick zu wahren.
13.4.5 BEGIN und END
Mit BEGIN und END haben Sie zwei Muster, die vollkommend unabhängig von der Eingabezeile sind. Man kann sich dies wie bei einer Schleife vorstellen. Alles, was sich vor dem eigentlichen awk-Script noch abspielen soll, können Sie in einen BEGIN-Block schreiben:
BEGIN { Aktionsteil }
Hier können Sie bspw. eine Vorverarbeitung für den eigentlichen Hauptteil von awk festlegen. Allerdings ist damit nicht die Vorverarbeitung der Eingabezeile gemeint, da diese zu dem Zeitpunkt, wenn der BEGIN-Block ausgeführt wird, noch gar nicht eingelesen wurde. Der Aktionsteil kann genauso wie schon bei den »normalen« Mustern verwendet werden.
you@host > awk 'BEGIN { print "Vorname Name Land" }
> /USA/ { printf "%-10s %-10s %-5s\n", $1, $2, $3 }' \
> mrolympia.dat
Vorname Name Land
Larry Scott USA
Sergio Oliva USA
Chris Dickerson USA
Lee Haney USA
Ronnie Coleman USA
Wenn der BEGIN-Block vor der Verarbeitung der Eingabezeile ausgeführt wird, werden Sie sich sicherlich wohl denken können, dass sich der END-Block auf die Ausführung nach der Verarbeitung einer Eingabezeile bezieht. Wenn also alle Zeilen im Hauptblock ausgeführt wurden, kann am Ende noch zur Nachbearbeitung ein END-Block angehängt werden. Der END-Block wird ausgeführt, nachdem die letzte Zeile einer Datei abgearbeitet wurde oder bei Eingabe von der Tastatur (Strg)+(D) gedrückt wurde. Hier das Beispiel mit dem BEGIN-Block, erweitert um einen END-Block:
you@host > awk 'BEGIN { print "\nVorname Name Land" } \
> /USA/ { printf "%-10s %-10s %-5s\n", $1, $2, $3 } \
> END { print "---------Ende------------" } ' mrolympia.dat
Vorname Name Land
Larry Scott USA
Sergio Oliva USA
Chris Dickerson USA
Lee Haney USA
Ronnie Coleman USA
---------Ende------------
Hier wird zuerst der BEGIN-Block ausgeführt – im Beispiel nichts anderes als eine einfache Ausgabe auf dem Bildschirm. Anschließend werden die einzelnen Zeilen der Datei mrolympia.dat eingelesen und alle Zeilen mit dem Muster »USA« formatiert mit printf ausgegeben. Am Ende wird der END-Block ausgeführt, was hier nur eine einfache Textausgabe auf dem Bildschirm bedeutet. Ein END-Block setzt übrigens in keiner Weise einen BEGIN-Block voraus und kann immer auch nach einem Hauptteil verwendet werden – oder natürlich ganz alleine:
you@host > awk '{ print } END { print "Tschüssss..." }'
Hallo
Hallo
Welt
Welt
(Strg)+(D)
Tschüssss...
Hier liest awk Zeile für Zeile von der Kommandozeile ein und gibt diese im Hauptblock mit print zurück. Dies geht so lange, bis Sie (Strg)+(D) drücken. Nach dem Beenden mit (Strg)+(D) wird noch der END-Block ausgeführt.
Ihre Meinung
Wie hat Ihnen das Openbook gefallen? Wir freuen uns immer über Ihre Rückmeldung. Schreiben Sie uns gerne Ihr Feedback als E-Mail an kommunikation@rheinwerk-verlag.de.
|