13.3 Grundlegende awk-Programme und -Elemente
Wenn man noch nie einen Baum gepflanzt hat, wird man keine ganzen Wälder anlegen. Daher folgen hier zunächst die grundlegenden Elemente bzw. die einfachen Anwendungen von awk. Was man für awk zuallererst benötigt, das ist die Ausgabe von Zeilen und alles, was mit den Zeilen zu tun hat, die Verwendung von Feldern (bzw. Wörtern) und die formatierte Ausgabe bzw. die Ausgabe in einer Datei.
13.3.1 Ausgabe von Zeilen und Zeilennummern
Am besten fängt man mit dem Einfachsten an:
you@host > awk '{print}'
Ein Test
Ein Test
Noch einer
Noch einer
Dieser Einzeiler macht nichts anderes, als alle Eingaben, die Sie mit (ENTER) abgeschlossen haben, wieder auf dem Bildschirm auszugeben. Und zwar so lange, bis Sie die Tastenkombination (Strg)+(D) (für EOF) drücken. Im Prinzip funktioniert dies wie bei einem einfachen cat. Schreiben Sie jetzt einen Dateinamen hinter dem awk-Programm
you@host > awk '{print}' mrolympia.dat
...
erhält awk seine Eingabe nicht mehr von der Tastatur, sondern entnimmt diese zeilenweise der Datei. Aber, so ein einfaches cat ist awk auch wieder nicht. Wollen Sie, dass awk bestimmte Wörter von der Tastatur herausfiltert, können Sie hierzu ein Muster verwenden:
you@host > awk '!/mist/ {print}'
Die ist kein Mist
Die ist kein Mist
Aber hier ist ein mist!
Ende
Ende
Hiermit wird jede Zeile, welche die Textfolge »mist« enthält, nicht ausgegeben.
Benötigen Sie die laufende Zeilennummer, steht Ihnen die awk-interne Variable NR zur Verfügung, die sich immer die aktuelle Nummer der Eingabezeile merkt.
you@host > awk '{print NR " : " $0}' mrolympia.dat
1 : Larry Scott USA 1965 1966
2 : Sergio Oliva USA 1967 1968 1969
...
...
8 : Dorian Yates Grossbritannien 1992 1993 1994 1995 1996 1997
9 : Ronnie Coleman USA 1998 1999 2000 2001 2002 2003 2004
Hiermit geben Sie die komplette Datei mrolympia.dat mitsamt der Zeilennummern auf dem Bildschirm aus. Eine weitere Besonderheit ist hier die Variable $0, die immer automatisch mit der gesamten eingelesenen Zeile belegt ist. Wollen Sie mit awk nach einem bestimmten Muster suchen und hierbei die entsprechende Zeile bei Übereinstimmung mit ausgeben, kann dies wie folgt realisiert werden:
you@host > awk '/Lee/ {print NR " : " $0}' mrolympia.dat
7 : Lee Haney USA 1984 1985 1986 1987 1988 1989 1990 1991
Es wird nach dem Muster »Lee« in der Datei mrolympia.dat gesucht und dann mitsamt der Zeilennummer ausgegeben.
Hinweis Sie können mit awk noch einen Schritt weiter gehen, wenn Sie nicht die Variablen NR verwenden wollen, indem Sie die Zeilen selbst hochzählen. Hierzu müssen Sie nur eine extra Variable einsetzen und diese hochzählen: awk '{print ++i, " : " $0}' mrolympia.dat
|
13.3.2 Felder
Die nächst kleinere Einheit nach den Zeilen sind die einzelnen Felder bzw. Wörter (abhängig von FS), in die jede Eingabezeile zerlegt wird. Allerdings ist es im Grunde falsch, bei awk von Wörtern zu sprechen, vielmehr sind es Felder. Standardmäßig werden die einzelnen Zeilen durch Leerzeichen und Tabulatorzeichen aufgetrennt und jeweils in eine eigene Variable gespeichert. Die Namen der Variablen entsprechen den Positionsparametern der Shell: $1, $2, $3 ...
Damit ist es ohne größeren Umweg möglich, einzelne Spalten aus einer Datei zu extrahieren, was u. a. auch ein Hauptanwendungsgebiet von awk ist. So können Sie z. B. ohne Probleme den Inhalt der Spalte 3 und 2 einer Datei ausgeben lassen:
you@host > awk '{print $3, $2}' mrolympia.dat
USA Scott
USA Oliva
Österreich Schwarzenegger
Argentinien Columbu
USA Dickerson
Libanon Bannout
USA Haney
Grossbritannien Yates
USA Coleman
Wollen Sie jetzt noch wissen, wie viele Titel einer der Teilnehmer gewonnen hat, können Sie die Variable NF (Number of Fields) verwenden:
you@host > awk '{print $3, $2, NF-3}' mrolympia.dat
USA Scott 2
USA Oliva 3
Österreich Schwarzenegger 7
Argentinien Columbu 2
USA Dickerson 1
Libanon Bannout 1
USA Haney 8
Grossbritannien Yates 6
USA Coleman 7
Hier wurde von NF der Wert 3 subtrahiert, da die ersten drei Spalten eine andere Bedeutung haben. Ich kann mir schon denken, wie die nächste Frage lauten könnte: Wie kann man dies jetzt noch nach der Anzahl von Titeln sortieren? Hier gibt es immer mehrere Wege – ich könnte folgenden anbieten:
you@host > awk '{print NF-3, $3, $2}' mrolympia.dat | sort -r
8 USA Haney
7 USA Coleman
7 Österreich Schwarzenegger
6 Grossbritannien Yates
3 USA Oliva
2 USA Scott
2 Argentinien Columbu
1 USA Dickerson
1 Libanon Bannout
Verwenden Sie NF mit einem Dollarzeichen davor ($NF), befindet sich darin immer das letzte Wort der Zeile. Das Vorletzte würden Sie mit $(NF–1) erreichen:
you@host > awk '{print $NF, $(NF-1)}' mrolympia.dat
1966 1965
1969 1968
1980 1975
1981 1976
1982 USA
1983 Libanon
1991 1990
1997 1996
2004 2003
you@host > awk '{print "Zeile " NR, "enhält " NF " Worte \
> (letztes Wort: " $NF "; vorletztes: " $(NF-1) ")"}' \
> mrolympia.dat
Zeile 1 enhält 5 Worte (letztes Wort: 1966 ; vorletztes: 1965)
Zeile 2 enhält 6 Worte (letztes Wort: 1969 ; vorletztes:1968
Zeile 3 enhält 10 Worte (letztes Wort: 1980 ; vorletztes: 1975)
Zeile 4 enhält 5 Worte (letztes Wort: 1981 ; vorletztes: 1976)
Zeile 5 enhält 4 Worte (letztes Wort: 1982 ; vorletztes: USA)
Zeile 6 enhält 4 Worte (letztes Wort: 1983 ; vorletztes:Libanon)
Zeile 7 enhält 11 Worte (letztes Wort: 1991 ; vorletztes: 1990)
Zeile 8 enhält 9 Worte (letztes Wort: 1997 ; vorletztes: 1996)
Zeile 9 enhält 10 Worte (letztes Wort: 2004 ; vorletztes: 2003)
Und natürlich gehört es zu den Grundlagen von Feldern, den Feldtrenner zu verändern. Dies kann über den Schalter –F oder in einem awk-Script über die Variable FS geschehen.
Formatierte Ausgabe und Dateiausgabe
Zur formatierten Ausgabe wurde bisher immer print verwendet, welches ähnlich wie echo in der Shell funktioniert. Da ja die einzelnen Felder anhand von Leerzeichen und Tabulatorzeichen getrennt werden, sollte es einleuchtend sein, dass bei der folgenden Ausgabe die Wörter nicht voneinander getrennt werden:
you@host > awk '{print $1 $2 }' mrolympia.dat
LarryScott
SergioOliva
...
...
DorianYates
RonnieColeman
Man kann entweder das Leerzeichen (oder auch ein anderes Zeichen bzw. andere Zeichenfolge) in Double Quotes eingeschlossen einfügen:
you@host > awk '{print $1 " " $2 }' mrolympia.dat
Oder aber man trennt die einzelnen Felder voneinander mit einem Komma:
you@host > awk '{print $1, $2 }' mrolympia.dat
Meistens reicht die Ausgabe von print. Aber auch hier haben Sie mit printf die Möglichkeit, Ihre Ausgabe erweitert zu formatieren. printf funktioniert hier genauso, wie es schon für die Shell beschrieben wurde, weshalb ich hier auf Tabellen mit den Typezeichen (s für String, d für Dezimal, f für Float usw.) verzichten kann. Bei Bedarf werfen Sie bitte einen Blick in Abschnitt 5.2.3. Gleiches gilt übrigens auch für die Escapesequenzen (alias Steuerzeichen) (siehe Tabelle 5.2). Einziger Unterschied im Gegensatz zum printf der Shell: Die Argumente am Ende müssen durch ein Komma getrennt werden. Ein einfaches Beispiel der formatierten Ausgabe mit printf:
you@host > awk ' \
> {printf "%-2d Titel\tLand: %-15s\tName: %-15s\n",NF-3,$3,$2}'\
> mrolympia.dat | sort -r
8 Titel Land: USA Name: Haney
7 Titel Land: USA Name: Coleman
7 Titel Land: Österreich Name: Schwarzenegger
6 Titel Land: Grossbritannien Name: Yates
3 Titel Land: USA Name: Oliva
2 Titel Land: USA Name: Scott
2 Titel Land: Argentinien Name: Columbu
1 Titel Land: USA Name: Dickerson
1 Titel Land: Libanon Name: Bannout
Zur Ausgabe in einer Datei wird für gewöhnlich eine Umlenkung verwendet:
you@host > awk \
> '{printf "%-2d Titel\tLand: %-15s\tName: %-15s\n",NF-3,$3,$2}'\
> mrolympia.dat > olymp.dat
you@host > cat olymp.dat
2 Titel Land: USA Name: Scott
3 Titel Land: USA Name: Oliva
7 Titel Land: Österreich Name: Schwarzenegger
2 Titel Land: Argentinien Name: Columbu
1 Titel Land: USA Name: Dickerson
1 Titel Land: Libanon Name: Bannout
8 Titel Land: USA Name: Haney
6 Titel Land: Grossbritannien Name: Yates
7 Titel Land: USA Name: Coleman
Es ist aber auch möglich, innerhalb von awk – im Aktionsteil – in eine Datei zu schreiben:
you@host > awk '/USA/{ print > "usa.dat"}' mrolympia.dat
you@host > cat usa.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
Im Beispiel wurden alle Zeilen mit einer Zeichenfolge »USA« in die Datei usa.dat geschrieben. Dies ist zum Beispiel sinnvoll, wenn Sie mehrere Muster-Aktions-Teile verwenden und nicht jede Ausgabe gleich in eine Datei geschrieben werden soll.
Um dem Ganzen die Krone aufzusetzen, folgendes Beispiel:
you@host > awk '$3 {print >> $3}' mrolympia.dat
Hier schreiben Sie für jedes Land den Inhalt des entsprechenden Eintrags ans Ende einer Datei mit dem entsprechenden Landesnamen. Genauer: Für jedes Land wird eine extra Datei angelegt, worin die einzelnen Teilnehmer immer ans Ende der Datei gehängt werden. Führen Sie das einmal in einer anderen Sprache mit einer Zeile durch.
you@host > ls -l
-rw------- 1 tot users 37 2005–04–11 15:34 Argentinien
-rw------- 1 tot users 58 2005–04–11 15:34 Grossbritannien
-rw------- 1 tot users 27 2005–04–11 15:34 Libanon
-rw------- 1 tot users 381 2005–04–08 07:32 mrolympia.dat
-rw------- 1 tot users 68 2005–04–11 15:34 Österreich
-rw------- 1 tot users 191 2005–04–11 15:34 USA
you@host > cat Libanon
Samir Bannout Libanon 1983
you@host > cat Österreich
Arnold Schwarzenegger Österreich 1970 1971 1972 1973 1974 1975
Natürlich können Sie das noch ganz anders erreichen:
you@host > awk '$3 {print $2, $1, $3 >> $3}' mrolympia.dat
Hier machen Sie das Gleiche, hängen jedoch nur den Inhalt der Felder $2, $3 und $1 an entsprechende Landesdatei. In Verbindung mit einer umfangreichen Datenbank ist das wirklich mächtig. Doch im Prinzip ist das noch gar nichts, awk ist bei richtiger Anwendung zu viel mehr im Stande.
Natürlich können Sie awk auch cat-ähnlich verwenden, um alle Eingaben von der Tastatur in eine Datei zu schreiben:
you@host > awk '{print > "atextfile"}'
Hallo Textdatei
Das steht drin
(Strg)+(D)
you@host > cat atextfile
Hallo Textdatei
Das steht drin
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.
|