gawk/Datenfelder und Variablen
Datenfelder und Variablen
Wichtige eingebaute Variablen
- Awk arbeitet unter der Annahme, dass die Eingabe strukturiert ist.
- Im einfachsten Fall interpretiert awk jede Eingabezeile als Datensatz und jedes enthaltene Wort als Feld. Ein Wort ist dabei jede von Feldseparatoren begrenzte Zeichenfolge.
- In der Voreinstellung trennen Leerzeichen und Tabulatoren Wörter; durch Belegung der builtin-Variablen FS lassen sich beliebige Separatoren definieren.
- Über den Feldoperator $ gestattet Awk den Zugriff auf die Felder der zuletzt eingelesenen Eingabezeile.
- Im Unterschied zur Programmiersprache C beginnt die Nummerierung der Felder bei 1 und - im Gegensatz zu den Positionsparametern der Shell - endet sie nicht bei 9 (implementierungsabhängig werden 100 Felder garantiert; gawk auf x86-Architektur kann vermutlich 232 Felder indizieren).
Um z. B. das 1. und 11. Feld einer Eingabezeile auszugeben, hilft Folgendes:
$ echo "0 1 2 3 4 5 6 7 8 9 10 11" | awk '{print $1,$11;}' 0 10
Der Feldoperator $0 steht für die gesamte Zeile; die Anzahl der Felder der aktuell bearbeiteten Zeile ist in der Variablen NF gespeichert.
$ echo "0 1 2 3 4 5 6 7 8 9 10 11" | awk '{print NF,$0;}' 12 0 1 2 3 4 5 6 7 8 9 10 11
- Die aktuelle Zeilennummer hält Awk in der Variablen NR.
Um die Zeilen einer Datei zu nummerieren, könnte somit folgender Aufruf dienen:
$ awk '{print NR,$0;}' <zu_nummerierende_Datei>
- Bei aufmerksamer Betrachtung des einführenden Beispiels »head.awk« ist Ihnen vermutlich aufgefallen, dass wir dort FNR anstatt NR zur Nummerierung verwendeten.
- Der Unterschied ist, dass Letzteres (NR) fortlaufend die Anzahl der Durchläufe der Hauptschleife zählt, während FNR im Falle mehrerer Eingabedateien die Zählung für jede Datei von vorn beginnt.
Beispiel
»wc -l« mit Mitteln von Awk, wobei außerdem die Variable FILENAME verwendet wird, die den Namen der aktuell bearbeiteten Datei enthält :
#!/usr/bin/awk -f BEGIN { zeile=0; } { if ( zeile > FNR ) { print zeile,FILENAME; zeile=0; } else zeile++; } END { print FNR, FILENAME if ( FNR != NR ) { print NR, "insgesamt"; } }
Als Testfall wenden wir das kleine Programm auf sich selbst an und vergleichen die Ausgabe mit der von »wc -l«:
$ ./wc-l.awk /etc/fstab /etc/passwd 17 /etc/passwd 46 /etc/passwd 63 insgesamt $ wc -l /etc/fstab /etc/passwd 17 /etc/fstab 46 /etc/passwd 63 insgesamt
- Abgesehen von der Formatierung (wir später noch behoben) verhält sich unser Programm exakt wie das Vorbild.
- Eher unüblich ist die Manipulation der Variablen RS, die den Zeilenseparator spezifiziert.
- Sinnvoll ist es für Datensätze, die über mehrere Zeilen verteilt stehen und ein anderes Zeichen (bspw.
- eine Leerzeile) eine eindeutige Strukturierung erlaubt.
- Das die Ausgabe von Awk betreffende Pedand zu RS ist der Output Record Selector (ORS).
- In der Voreinstellung dient der Zeilenumbruch zur Separierung der Ausgaben; durch Neubelegung von ORS kann dies geändert werden.
- Nachfolgender Kommandoaufruf ersetzt die Unix-Dateiendung (Newline) durch das Windows-Äquivalent (Carriage Return, Newline):
$ awk 'BEGIN {ORS="\r\n";}{print $0;}' <Datei>
- Natürlich hätte es auch »recode« getan...
- Neben ORS zum Ändern des Zeilenseparators existiert mit OFS eine Variable, die das Trennzeichen für einzelne Datenfelder (Voreinstellung: Leerzeichen) festlegt.
Weitere eingebaute Variablen
- Die weiteren von Awk verwendeten internen Variablen sollen an dieser Stelle nur kurz benannt werden.
- Einigen Vertretern werden wir später erneut begegnen.
CONVFMT | Steuert die Konvertierung von Zahlen in Zeichenketten.
$ awk 'BEGIN { print "Pi = " 3.1415926532; }' Pi = 3.14159 $ awk 'BEGIN { CONVFMT="%.10g"; print "Pi = " 3.1415926532; }' Pi = 3.141592653 |
ENVIRON | Die Feldvariable ENVIRON enthält alle Umgebungsvariablen.
$ awk 'BEGIN { print ENVIRON["HOME"]; }' /home/user |
IGNORECASE | Steuert die Unterscheidung von Klein- und Großschreibung beim Mustervergleich.
|
OFMT | OFMT steuert das Ausgabeformat von Zahlen durch das Kommando print. Die Verwendung erfolgt analog zu CONVFMT |
RLENGTH | Länge der übereinstimmenden Teilzeichenkette der Zeichenkettenfunktion match() |
RSTART | Index des Beginns der übereinstimmenden Teilzeichenkette mit der Zeichenkettenfunktion match() |
SUBSEP | Das Zeichen, das in Feldvariablen die einzelnen Elemente trennt (\034). |
Eigene Variablen
Datentypen
- Awk unterscheidet einzig (Gleitkomma-)Zahlen und Zeichenketten.
- Von welchem Typ eine Variable ist, hängt vom aktuellen Kontext ab.
- Findet eine numerische Berechnung statt, werden die beteiligten Variablen als Zahlen interpretiert und bei Zeichenkettenoperationen eben als Zeichenketten.
- Notfalls lässt sich ein konkreter Kontext erzwingen, indem bspw.
- der Wert '0' zu einer Variable addiert oder die leere Zeichenkette "" an eine solche angehangen wird.
Internen Konvertierungen
- Für den Awk-Programmierer von Interesse sind die internen Konvertierungen, die beim Vergleich von Variablen stattfinden.
- Zwei numerische Variablen werden als Zahlen verglichen, genauso wie zwei Zeichenkettenvariablen als Zeichenketten verglichen werden.
- Ist eine Variable eine Zahl und die andere eine numerische Zeichenkette, so wird die Zeichenkette in eine Zahl konvertiert.
- Handelt es sich um keine numerische Zeichenkette, wird die Variable mit der Zahl in eine Zeichenkette gewandelt und nachfolgend ein Vergleich der Zeichenketten vorgenommen.
Variablennamen
- Variablennamen in Awk dürfen aus Buchstaben, Ziffern und dem Unterstrich bestehen, wobei zum Beginn keine Ziffer stehen darf.
- Klein- und Großschreibung werden unterschieden, sodass bspw.
- Variable, variable, und VARIABLE unterschiedliche Bezeichner sind.
- Eine Variable wird definiert, indem sie benannt und ihr ein Wert zugewiesen wird.
- Die in anderen Programmiersprachen üblichen Typbezeichner kennt Awk nicht.
- Eine Variable kann auch nur deklariert werden, awk initialisiert sie dann selbsttätig als leeren Zeichenkette.