Kapitel 2 Bedingungen und Variablen2.1 BedingungenWir haben bereits die Bedingung /[text]/ kennengelernt, die nach dem Text [text] sucht. Dabei kann [text] auch einfache so genannte reguläre Ausdrücke enthalten:
Will man eines dieser speziellen Zeichen im Klartext finden, so muss ein Backslash, der rückläufige Schrägstrich, vorangestellt werden: \. findet einen Punkt, \\ einen Backslash. Der Backslash kann auch bei anderen Zeichen benutzt werden, er findet dann dieses Zeichen. Wer also nicht genau weiß, ob ein Zeichen eine besondere Bedeutung hat, stellt einfach einen Backslash voran: \Y findet ein großes Ypsilon. Es gibt weitere Bedingungen, die meist in einer der Programmiersprache C ähnlichen Syntax angegeben werden:
a == b ist wahr, wenn a und b gleich sind. Das Skript $1=="NODE" { print $2 } schreibt also das zweite Wort heraus, wenn das erste »NODE« ist. Zeichenketten, so genannte Strings, müssen hier immer in Anführungszeichen stehen, um deutlich zu machen, dass es sich um einen String und nicht um eine Variable handelt. Vorsicht bei der Prüfung auf Gleichheit: a = b belegt a mit dem Wert von b. In awk muss die Prüfung auf Gleichheit wie in C mit einem doppelten Gleichheitszeichen erfolgen! (Es ist sogar noch schlimmer: a = b ist für awk wahr, wenn b nicht Null ist. Die Belegung von a erfolgt aber trotzdem: Etwas wie wie $1="xxx" { print $1, $2, $3 } hat merkwürdige Folgen.) Für Strings gibt es zwei weitere Operatoren: ~ und !~, die prüfen, ob ein String einen regulären Ausdruck enthält oder nicht. /^[0-9]/ und $0 ~ /^[0-9]/ bewirken dasselbe: Sie überprüfen, ob die Zeile mit einer Ziffer beginnt. Mit ~ kann man also beliebige Strings auf reguläre Ausdrücke hin überprüfen. Bedingungen können mit so genannten logischen Operatoren miteinander verknüpft werden:
Bedingungen können weiterhin in Klammern geschachtelt werden, um Prioritäten bei der Auswertung zu setzen. Außerdem gibt es noch zwei nützliche Regeln aus der Logik, die Gesetze von de Morgan: !(a && b) == !a || !b !(a || b) == !a && !b Außerdem können zwei Bedingungen hintereinander, durch ein Komma getrennt, angegeben werden. Dann werden die Anweisungen für alle Zeilen ausgeführt, die zwischen einer Zeile, für die die erste Bedingung gilt, und der nächsten, für die die zweite gilt, liegen. /Anfang/, /Ende/ Schreibt alle Zeilen, die zwischen den Wörtern »Anfang« und »Ende« liegen. Die erste Bedingung ist also eine Start-, die zweite eine Abbruchbedingung. Es gibt noch zwei weitere Bedingungen in awk, die sehr wichtig sind, die wir aber erst später benutzen werden:
2.2 VariablenDas Konzept der Variablen in awk ist sehr mächtig. Variablen müssen nicht, wie in Programmiersprachen allgemein üblich, deklariert werden, bevor sie benutzt werden. Um eine Variable zu benutzen, setzt man sie einfach im Skript ein. Jede Varaible hat zu Beginn des Skripts den Wert 0. Dazu ein Beispiel: awk '/NODE/ { n = n+1 }; END { print n }' xxx.dat Dieses Skript zählt die Zeilen, in denen »NODE« vorkommt, in der Variable n und gibt n am Ende aus. Dies ist äquivalent zu grep -c NODE xxx.dat Verschiedene Anweisungen können durch Semikola oder Zeilenumbrüche voneiander getrennt hintereiander angegeben werden. Letzteres funktioniert natürlich nur, wenn das Skript in einer separaten Datei steht. Wenn eine Anweisung über mehrere Zeilen geht, so müssen alle Zeilen der Anweisung außer der letzten mit einem Backslash enden. Anstelle der Anweisung n = n + 1, die wörtlich bedeutet: »Weise der Variable n den jetzigen Wert von n plus eins zu, und die nichts anderes macht, als n um eins zu erhöhen, kann man in awk abkürzend schreiben n++. Variablen in awk können zwei Grundtypen besitzen: Zahl oder String. Dabei ist awk bei der Interpretation, um welchen Typ es sich handelt, flexibel. Mit Zahlen können folgende Operationen durchgeführt werden:
+ Addition Das Ergebnis der Division ist eine Fließkommazahl. Mit Modulo-Division bezeichnet man den Rest einer Ganzzahldivision: 7%3 ist 1, da sieben geteilt durch drei einen Rest von eins lässt. Für alle diese Funktionen gibt es Abkürzungen, wenn dieselbe Variable auf beiden Seiten vorkommt. So kann man x = x + 10 als x += 10 schreiben. Analog dazu gibt es die Operatoren -=, *=, /=, %= und ^=. Diese Schreibweise ist für Anfänger aber oft verwirrend, deshalb ist es vermutlich besser, den Ausdruck komplett anzugeben. Die Operatoren ++ und -- können vor oder hinter Variablen stehen. ++ vor einer Variable (Präfix) bedeutet »erhöhe die Variable um eins, und werte dann aus«, nach einer Variable (Postfix) bedeute es »werte die Variable aus, erhöhe sie dann um eins«. Ist x 5, so erhöht sich der Wert bei print ++x und bei print x++ in beiden Fällen auf 6. Im ersten Fall wird jedoch »6«, im zweiten »5« ausgegeben. Die einzige elementare Funktion für Strings ist das Anhängen eines anderen Strings, das einfach durch Hintereinaderschreiben der Strings, durch mindestens ein Blank getrennt, geschieht: name = "Hans" "Meiser"; print name; gibt »HansMeiser« aus. Es wird also kein Leer- oder anderes Zeichen zwischen die verketteten Strings geschrieben. Wie bereits erwähnt, können Variablen ihren Typ ändern. Führt man mit Strings eine mathematische Operation durch, so ist das Ergebnis eine Zahl. Andersherum geht es aber auch: Fügt man an eine Zahl einen String an, so ist das Ergebnis ein String. Dazu ein Beispiel: $1=="NODE" {x = x + $2; n = n + 1} END {print x, n, x/n} Hier werden für alle Zeilen, in denen das erste Wort »NODE« ist, die Zahlenwerte der zweiten »Wörter« aufaddiert. Am Ende wird die Summe, die Anzahl und der Durchschnitt ausgegeben. Es gibt keine explizite Anweisung, um Strings in Zahlen umzuwandeln und umgekehrt. Um sicherzugehen, kann man folgendes machen: x + 0 ist eine Zahl, x "" ist ein String. ("" ist der Nullstring, ein String ohne Inhalt.) Der numerische Wert von Strings, die keine Zahl enthalten, ist Null: "Anna" hat einen numerischen Wert von Null. awk kann aber die Exponentialschreibweise für Fließkommazahlen erkennen: "2.4E-3" wird korrekt als 0,0024 interpretiert. Aufgaben: Aufgabe 2a Aufgabe 2b Aufgabe 2c Aufgabe 2d Aufgabe 2e
|
|