awk/Ausdrücke
Ausdrücke sind die grundlegenden Bausteine von awk-Mustern und -Aktionen. Ein Ausdruck besteht aus einem Wert, der ausgegeben, getestet oder an eine Funktion übergeben werden kann. ZUsätzlich kann ein Ausdruck einer Variable oder einem Feld einen neuen Wert zuweisen, indem ein Zuweisungsoperator verwendet wird.
Ein Ausdruck kann als Muster- oder Aktionsanweisung dienen. Die meisten anderen Arten von Anweisungen enthalten einen oder mehrere Ausdrücke, welche die zugrundeliegenden Daten bestimmen. Wie in anderen Programmiersprachen enthalten Ausdrücke awk Variablen, Arrayreferenzen, Konstanten, Funktionsaufrufe sowie Kombinationen daraus mit verschiedenen Operatoren.
Konstante Ausdrücke
Der einfachste Ausdruck ist die Konstante, die immer denselben Wert besitzt. Es gibt drei Arten von Konstanten: numerische Konstanten, Zeichenkettenkonstanten und regexp-Konstanten.
Numerische und Zeichenkettenkonstanten
Eine numerische Konstante steht für eine Zahl. Diese Zahl kann eine Ganzzahl sein, ein Dezimalbruch oder eine Zahl in wissenschaftlicher Notation. Einige Beispiele für numerische Konstanten sind:
105 1.05e+2 1050e-1
Eine Zeichenkettenkonstante besteht aus einer Folge von Zeichen, die in Anführungszeichen eingeschlossen sind. Zeichenketten können in gawk beliebige Länge besitzen und jedes mögliche 8-Bit-ASCII-Zeichen enthalten (einschliesslich ASCII NUL). Folgendes Beispiel ist also eine Zeichenkette mit dem Inhalt "Papagei".
"Papagei"
Oktale und hexadezimale Zahlen
In awk sind alle Zahlen dezimal, verwendet also die Grundzahl 10. Viele andere Programmiersprachen erlauben die Verwendung von Zahlen mit anderen Grundzahlen, oft oktale (Grundzahl 8) und hexadezimale (Grundzahl 16).
Im oktalen Zahlensystem gibt es die Zahlen 0, 1, 2, 3, 4, 5, 6, 7, 11, 12 usw. Genauso wie 11 im Dezimalsystem einmal 10 plus 1 entspricht, so ist 11 im Oktalsystem eben 8 plus 1, was im Dezimalsystem der Zahl 9 entspricht.
Im hexadezimalen Zahlensystem gibt es 16 Ziffern. Weil das alltägliche Dezimalsystem nur zehn Ziffern (0-9) hat, werden die Buchstaben a bis f zur Darstellung der Ziffern 11 bis 16 verwendet. 11 im Hexadezimalsystem entspricht also einmal 16 plus 1, was im Dezimalsystem der Zahl 17 entspricht.
Um eine gegebene Zahl einem bestimmten Zahlensystem zuordnen zu können, wird eine besondere Notation verwendet. Oktale Zahlen beginnen mit einer führenden "0", hexadezimale Zahlen beginnen mit den führenden Zeichen "0x" oder "0X".
- "11" entspricht dem dezimalen Wert 11.
- "011" entspricht dem oktalen Wert 11 und dem dezimalen Wert 9.
- "0x11" entspricht dem hexadezimalen Wert 11 und dem dezimalen Wert 17.
Folgendes Beispiel zeigt die Unterschiede.
$ gawk 'BEGIN { printf "%d, %d, %d\n", 11, 011, 0x11 }' 11, 9, 17
Die Zahlen 8 und 9 sind keine gültigen Oktalkonstanten. Beispielsweise behandelt gawk 008, 009 und auch 018 einfach als Dezimalzahlen 8, 9 und 18.
$ gawk 'BEGIN { print "021 ist" , 021; print 008, 009, 018 }' 021 ist 17 8 9 18
regexp-Konstanten
Eine regexp-Konstante ist ein in Schrägstrichen eingeschlossener regulärer Ausdruck wie z. B. "/^Anfang und Ende$/". Die meisten in awk verwendeten regulären Ausdrücke sind Konstanten, doch die Übereinstimmungsoperatoren "~" und "!~" können auch mit berechneten oder "dynamischen" regulären Ausdrücken übereinstimmen (welche bloss gewöhnliche Zeichenketten oder Variablen sind, die einen regulären Ausdruck enthalten).
Sobald eine numerische Konstante intern in eine Zahl umgewandelt wurde, erinnert sich gawk nicht mehr an die ursprüngliche Form einer solchen Konstante und verwendet immer den internen Wert. Das hat besondere Konsequenzen bei der Umwandlung von Zahlen in Zeichenketten:
$ gawk 'BEGIN { printf "0x11 ist <%s>\n", 0x11 }' 0x11 ist <17>
Bei Verwendung einer regexp-Konstante auf der rechten Seite des "~" oder "!~" Operators steht sie bloss für den regulären Ausdruck, mit dem sie übereinstimmen soll. regexp-Konstanten (z. B. "/foo/") können wie einfache Ausdrücke verwendet werden. Wenn eine regexp-Konstante allein erscheint hast sie dieselbe Bedeutung wie wenn sie in einem Muster erscheinen würde (z. B. "$0 ~ /foo/"). Die folgenden beiden Codeausschnitte bedeuten also genau dasselbe.
if ($0 ~ /barfly/ || $0 ~ /camelot/) print "found" if (/barfly/ || /camelot/) print "found"
Eine ziemlich bizarre Konsequenz dieser Regel ist, dass der folgende Boolesche Ausdruck zwar gültig ist, aber vermutlich nicht das tut, was der Benutzer beabsichtigt hat. Dabei wird "offensichtlich" "$s+ für eine Übereinstimmung mit dem regulären Ausdruck "/foo/" getestet. In Wirklichkeit allerdings bedeutet der Ausdruck "/foo/ ~ $1" soviel wie "($0 ~ /foo/) ~ $1". Anders gesagt wird zuerst der Eingabedatensatz mit dem regulären Ausdruck "/foo/" verglichen. Das Ergebnis ist entweder 0 oder 1, je nach Erfolg oder Misserfolg der Übereinstimmung. Dieses Ergebnis wird danach mit dem ersten Feld des Datensatzes verglichen. Da ein solcher Test wohl kaum je gewünscht wird, gibt gawk im Fall eines solchen Konstrukts eine Warnung aus.
# Achtung: /foo/ ist auf der linken Seite von ~ if (/foo/ ~ $1) print "found foo"
Eine andere Konsequenz dieser Regel ist, dass folgende Anweisung der Variable "matches" entweder den Wert 0 oder 1 zuweist, je nach dem Inhalt des aktuellen Eingabedatensatzes.
matches = /foo/
regexp-Konstanten werden auch als erstes Argument der Funktionen "gensub", "sub" und "gsub" verwendet, sowie als zweites Argument der Funktion "match" und als drittes Argument der Funktion "split".
Variablen
Variablen sind Wege, um Werte an einer Stelle des Programms für späteren Gebrauch zu speichern. Sie können vollständig innerhalb des Programmtexts verändert werden und ihnen kann auch auf der awk-Befehlszeile ein Wert zugewiesen werden.
Variablen in einem Programm
Mit Variablen kann einem Wert ein Name gegeben und später auf ihn zurückverwiesen werden. Der Name einer Variable muss aus einer Folge von Zeichen, Zahlen oder Unterstrichen bestehn und darf nicht mit einer Zahl beginnen. Gross- und Kleinschreibung wird beachtet, sodass "A" und "a" zwei unterschiedliche Variablen sind.
Ein Variablenname ist selbst bereits ein gültiger Ausdruck und repräsentiert den aktuellen Wert der Variable. Variablen kann über Zuweisungs-, Erhöhungs- und Erniedrigungsoperatoren ein neuer Wert zugewiesen werden.
Einige Variablen haben besondere eingebaute Bedeutungen, z. B. "FS" (der Feldtrenner) und "NF" (die Anzahl Felder im aktuellen Eingabedatensatz). Diese eingebauten Variablen können wie alle anderen Variablen verwendet werden, ihre Werte werden allerdings auch von awk verwendet oder verändert. Alle eingebauten Variablennamen sind in Grossbuchstaben geschrieben.
Variablen können entweder Zahlen- oder Zeichenkettenwerte zugewiesen werden. Die Art der Variable kann sich während des Lebens eines Programms auch verändern. Standardmässig werden Variablen als leere Zeichenketten initialisiert, was bei Umwandlung in eine Zahl eine "0" ergibt. Es gibt in awk keine Notwendigkeit, eine Variable zu "initialisieren".
Variablen auf der Befehlszeile zuweisen
Jede awk-Variable kann beim awk-Aufruf durch Hinzufügen einer Variablenzuweisung zu den Argumenten gesetzt werden. Eine solche Zuweisung hat folgende Form und kann entweder am Beginn des awk-Aufrufs oder zwischen einzelnen Eingabedateien gesetzt werden.
variable=text
Im folgenden Beispiel wird die Variable ganz zu Beginn gesetzt, sogar noch vor den "BEGIN"-Regeln. Die Option "-v" muss dabei vor allen Dateiargumenten und vor dem Programmtext stehen.
-v variable=text
Im anderen Fall wird eine Variable zu dem Zeitpunkt gesetzt, der durch ihre Position innerhalb der Dateiargumente bestimmt wird - also nach der Verarbeitung des vorangehenden Dateiarguments. Im folgenden Beispiel wird der Wert von Feldnummer "n" für alle Eingabedatensätze ausgegeben. Bevor die erste Datei gelesen wird, wird die Variable "n" auf "4" gesetzt. Damit wird das vierte Feld aus der folgenden Datei "inventory" ausgegeben. Nach Beendigung der ersten Datei wird "n" auf "2" gesetzt und so das zweite Feld der Datei "bbslist" ausgegeben.
$ awk '{ print $n }' n=4 inventory n=2 bbslist 15 24 ... 555-5553 555-3412 ...
Umwandlung von Zeichenketten und Zahlen
Zeichenketten werden in Zahlen und Zahlen in Zeichenketten ungewandelt, wenn der Kontext des awk-Programms es verlangt. Wenn beispielsweise der Wert von entweder "foo" oder "bar" im Ausdruck "foo + bar" eine Zeichenkette ist, so wird er vor der durchzuführenden Addition in eine Zahl umgewandelt. Wenn Zahlenwerte in Zeichenketten erscheinen, so werden sie in Zeichenketten umgewandelt.
Das folgende Beispiel gibt den Zahlenwert "27" aus. Die Zahlenwerte der Variablen "zwei" und "drei" wird in Zeichenketten umgewandelt und aneinandergehängt. Die daraus entstehende Zeichenkette "23" wird in die Zahl "23" zurückverwandelt, worauf "4" dazu addiert wird.
zwei = 2; drei = 3 print (zwei drei) + 4
Um die Umwandlung eines Zahlenwerts in eine Zeichenkette zu erzwingen, muss die leere Zeichenkette ("") mit dieser Zahl verbunden werden.
Um die Umwandlung einer Zeichenkette in eine Zahl zu erzwingen, muss eine "0" zu dieser Zeichenkette addiert werden.
Eine Zeichenkette wird in eine Zahl umgewandelt, indem jegliche führende Zahl als Zahl angesehen wird: "2.5" wird in "2.5" umgewandelt, "1e3" wird in "1000" umgewandelt, und "25fix" hat den Zahelnwert "25". Zeichenketten, die nicht als gültige Zahlen interpretiert werden können, werden in den Zahlenwert "0" umgewandelt.
Die genaue Art, in der Zahlen in Zeichenketten umgewandelt werden, wird durch die in awk eingebaute Variable "CONVFMT" bestimmt. Zahlen werden unter Verwendung der Funktion "sprintf" umgewandelt, wobei "CONVFMT" als Formatbestimmer wirkt.
Der Standardwert von "CONVFMT" ist "%.6g", das einen Wert mit mindestens sechs signifikanten Ziffern ausgibt. Auf modernen Rechnern werden 17 Ziffern normalerweise als ausreichend betrachtet. Seltsame Ergebnisse können entstehen, wenn "CONVFMT" auf eine Zeichenkette gesetzt wird, die der Funktion "sprintf" nicht sagt, wie eine Fliesskommazahl sinnvoll zu formatieren ist. Wird beispielsweise das Zeichen "%" vergessen, so wandelt awk alle Zahlen in dieselbe Zeichenkette um. Ein Spezialfall ist es, wenn eine Zahl eine Ganzzahl ist, denn dann wird das Ergebnis immer als Ganzzahl erscheinen, gleichgültig was der Wert von "CONVFMT" ist. Im folgenden Beispiel hat "b" deshalb den Wert "12", nicht "12.00".
CONVFMT = "%2.2f" a = 12 b = a ""
Arithmetische Operatoren
awk verwendet die üblichen arithmetischen Operatoren zur Berechnung von Ausdrücken.
Das folgende Beispiel gibt den Durchschnitt der Monate aus.
$ awk '{ sum = $2 + $3 + $3 + $4 ; avg = sum / 4 print $1, avg }' inventory Jan 19.5 Feb 25.75 ...
Folgende Liste zeigt alle arithemtischen Operatoren, von der höchsten Wertigkeit bis zur niedrigsten. Unäres Plus und Minus haben dieselbe Rangordnung. Die Multiplikationsoperatoren haben alle dieselbe Rangordnung. Addition und Subtraktion haben dieselbe Rangordnung.
- x | Unäres Minus. Negation. |
+ x | Unäres Plus. Der Ausdruck wird in eine Zahl umgewandelt. |
x ^ y x ** x |
Potenzieren. "x" wird in die "y"te Potenz erhoben. "2 ^ 3" hat den Wert "8". |
x * y | Multiplikation. |
x / y | Division. Weil alle Zahlen in awk Fliesskommazahlen sind, wird das Ergebnis nicht auf eine Ganzzahl gerundet, "3 / 4" hat also den Wert "0.75". |
x % y | Rest |
x + y | Addition. |
x - y | Subtraktion. |
Bei der Berechnung des Rests von "x % y" wird der Rest in Richtung 0 auf eine Ganzzahl gerundet und mit "y" multipliziert. Dieses Ergebnis wird von "x" abgezogen. Diese Operation wird auch als "trunc-mod" bezeichnet. Folgende Beziehung stimmt immer:
b * int(a / b) + (a % b) == a
Ein möglicher unerwünschter Effekt dieser Definition des Rests ist, dass "x % y" negativ ist, wenn "x" negativ ist:
-17 % 8 = -1
Zeichenkettenverknüpfung
Es gibt nur eine Zeichenkettenoperation: die Verknüpfung. Sie wird erreicht, indem Ausdrücke ohne Operator nebeneinander geschrieben werden.
$ awk '{ print "Feldnummer eins: " $1 }' bbslist Feldnummer eins: aardvark Feldnummer eins: alpo-net ...
Weil die Zeichenkettenverknüpfung keinen eigenen Operator hat, müssen die zu verknüpfenden Elemente oft in Klammern geschrieben werden, damit im richtigen Moment angewandt wird. Im folgenden Beispiel werden "datei" und "name" nicht verknüpft.
datei = "datei" name = "name" print "irgendwas sinnvolles" > file name
Stattdessen muss folgendes geschrieben werden:
print "irgendwas sinnvolles" > (file name)
Die Verwendung von Klammern bei der Zeichenkettenverknüpfung ist grundsätzlich immer zu empfehlen.
Zuweisungsausdrücke
Eine Zuweisung ist ein Ausdruck, der einen Wert in einer Variable speichert. Im folgenden Beispiel wird der Variable "z" der Wert "1" zugewiesen.
z = 1
Zuweisungen können auch Zeichenketten entahlten. Im folgenden Beispiel wird die Variable "nachricht" den Wert "Dieses Essen ist gut" enthalten.
ding = "Essen" wertung = "gut" nachricht = "Dieses" ding " ist " wertung
Variablen haben keinen permanenten Typ. Der Typ der Variable ist immer der Typ des Werts, der ihr gerade zugewiesen ist. Im folgenden Beispiel hat die Variable "foo" erste einen Zahlenwert und später den einer Zeichenkette.
foo = 1 print foo foo = "bar" print foo
Zeichenkettenwerte, die nicht mit einer Ziffer beginnen, haben einen Zahlenwert von "0". Nach Ausführung des folgenden Codes wird der Wert der Variable "foo" deshalb "5" betragen:
foo "Eine Zeichenkette." foo = foo + 5
Eine Zuweisung ist ein Ausdruck, hat also einen Wert - eben den zugewiesenen Wert. "z = 1" ist also ein Ausdruck mit dem Wert "1". Konsequenterweise können mehrere Zuweisungen zusammengeschrieben werden. Das folgende Beispiel speichert den Wert "5" in allen drei Variablen "x", "y" und "z".
x = y = z = 5
Ausser "=" gibt es weitere Zuweisungsoperatoren, die den alten Wert der Variable neu berechnen:
Arithmetische Zuweisungsoperatoren | |
---|---|
lvalue += Inkrement | Addiert "Inkrement" zum Wert von "lvalue". |
lvalue -= Dekrement | Subtrahiert "Dekrement" vom Wert von "lvalue". |
lvalue *= Koeffizient | Multipliziert den Wert von "lvalue" mit dem "Koeffizienten". |
lvalue /= Divisor | Dividiert den Wert von "lvalue" durch den Divisor. |
lvalue %= Modulus | Setzt "lvalue" auf seinen Rest des "Modulus". |
lvalue ^= Potenz<brlvalue **= Potenz | Erhebt "lvalue" in die Potenz "Potenz". In POSIX existiert "**=" nicht. |
In den folgenden beiden gleichwertigen Beispielen wird dem Wert der Variable "foo" der Wert "5" hinzugefügt.
foo = foo + 5 foo += 5
In bestimmten Fällen ist der Gebrauch des Zuweisungsoperators "+=" allerdings nicht dasselbe wie die einfache Wiederholung des linksseitigen Operanden im rechtsseitigen Ausdruck. Siehe dazu Effective awk programming Seite 90.
Inkrement- und Dekrementoperatoren
Inkrement- und Dekrementoperatoren erhöhen oder erniedrigen den Wert einer Variable um den Wert "1". Die Zuweisungsoperatoren können dasselbe bewirken, sodass die Inkrement- und Dekrementoperatoren blosse Abkürzungen für bereits bekannte Vorgänge sind.
Der Operator "++" addiert den Wert "1". Er kann verwendet werden, um den Wert einer Variable entweder vor oder nach dem Auslesen zu erhöhen.
- Um die Variable "v" vorher zu erhöhen, wird "++v" geschrieben, womit der Wert der Variable "v" um den Wert "1" erhöht wird. Der Zuweisungsausdruck "v += 1 " ist vollkommen gleichwertig.
- Um die Variable "v" danach zu erhöhen, wird "v++" geschrieben., womit der Wert der Variable "v" um den Wert "1" erhöht wird. Der Unterschied ist allerdings, dass der Inkrementausdruck selber den Wert der alten Variable erhält. Hat beispielsweise "v" den Wert "4", so hat der Ausdruck "v++" den Wert "4", ändert aber den Wert von "v" auf "5". Der Operator gibt also den alten Wert der Variable zurück, erhöht sie aber gleichzeitig um den Wert "1". Der Zuwesiungsausdruck "(v += 1) -1" ist damit beinahe gleichwertig; da alle Zahlen in awk Fliesskommazahlen sind, entspricht "v + 1 - 1" bei sehr grossen Zahlen nicht unbedingt "v".
Felder und Arrayelemente werden genaus wie Variablen erhöht.
Der Dekrementoperator "--" arbeitet genau wie der Inkrementoperator "++", ausser dass er den wert "1" subtrahiert, anstatt ihn zu addieren.
++v | Der Ausdruck erhöht den Wert der Variable "v" um den Wert "1". Der neue Wert wird zum Wert des Ausdrucks. |
v++ | Der Ausdruck erhöht den Wert der Variable "v" um den Wert "1". Der Ausdruck behält seinen alten Wert. |
--v | Der Ausdruck erniedrigt den Wert der Variable "v" um den Wert "1". Der neue Wert wird zum Wert des Ausdrucks. |
v-- | Der Ausdruck erniedrigt den Wert der Variable "v" um den Wert "1". Der Ausdruck behält seinen alten Wert. |
Wahr und Falsch in awk
Viele Programmiersprachen haben eine besondere Darstellungsart für die Konzepte von "wahr" und "falsch". Üblicherweise werden dazu die Spezialkonstanten "true" und "false" verwendet. awk dagegen borgt ein einfaches Konzept von wahr und falsch von C: in awk gilt jeder Zahlenwert ungleich "0" und jede nicht-leere Zeichenkette als wahr. Jeder andere Wert, also "0" oder die leere Zeichenkette "", ist falsch.
Das folgende Programm gibt "Ein seltsamer Wahrheitswert" dreimal aus. Dabei ist zu sehen, dass die Zeichenkettenkonstante "0" als wahr gilt, da es sich um keine leere Zeichenkette handelt!
$ awk 'BEGIN { if (3.1415927) print "Ein seltsamer Wahrheitswert" if ("Vor sieben Jahren") print "Ein seltsamer Wahrheitswert" if (j = 57) print "Ein seltsamer Wahrheitswert" }' Ein seltsamer Wahrheitswert Ein seltsamer Wahrheitswert Ein seltsamer Wahrheitswert
Variablentypen und Vergleichsausdrücke
Variablen haben in awk keinen festen Typ. Stattdessen können sie entweder eine Zahl oder eine Zeichenkette sein, je nach dem ihnen zugewiesenen Wert. In gawk gilt folgendes:
- Eine Zahlenkonstante oder das Ergebnis einer numerischen Operation hat das Attribut "numeric".
- Eine Zeichenkettenkonstante oder das Ergebnis einer Zeichenkettenoperation hat das Attribut "string".
- Felder, "getline"-Eingaben, "FILENAME", "ARGV"-Elemente, "ENVIRON"-Elemente und die Elemente eines Arrays, das durch die Funktion "split" erzeugt wurde, die numerische Zeichenketten sind, haben das Attribut "strnum". Anderfalls haben sie das Attribut "string". Uninitialisierte Variablen haben ebenfalls das Attribut "strnum".
- Attribute verbreiten sich über Zuweisungen, werden aber durch keine Verwendung geändert.
Die letzte Regel ist besonders wichtig. Im folgenden Programm hat die Variable "a" den Typ "numeric", obwohl sie später in einer Zeichenkettenoperation verwendet wird.
$ awk 'BEGIN { a = 12.345 b = a " ist eine hübsche Zahl" print b }' 12.345 ist eine hübsche Zahl
Wenn zwei Operanden miteinander verglichen werden, wird entweder ein Zeichenkettenvergleich oder ein numerischer Vergleich gemacht. Dies hängt von den Attributen der Operanden gemäss folgender Tabelle ab.
STRING | NUMERIC | STRNUM | |
---|---|---|---|
STRING | string | string | string |
NUMERIC | string | numeric | numeric |
STRNUM | string | numeric | numeric |
Die zugrundeliegende Idee ist, dass eine numerisch aussehende Benutzereingabe - und nur Benutzereingabe - numerisch behandelt werden sollte, sogar wenn sie tatsächlich aus Zeichen besteht und eigentlich eine Zeichenkette ist. So ist beispielsweise die Zeichenkettenkonstante " +3.14" eine Zeichenkette, auch wenn sie numerisch aussieht und wird zu Vergleichszwecken niemals als Zahl behandelt. Kurz gesagt wird also ein Zeichenkettenvergleich durchgeführt, wenn mindestens ein Operand eine "reine" Zeichenkette ist (z. B. eine Zeichenkettenkonstante). Andernfalls wird ein numerischer Vergleich durchgeführt.
Vergleichsausdrücke vergleichen Zeichenketten oder Zahlen miteiander. Sie werden unter Verwendung der folgenden Beziehungsoperatoren geschrieben.
Ausdruck | Ergebnis |
---|---|
x < i | Wahr, wenn "x" kleiner als "y" ist. |
x <= i | Wahr, wenn "x" kleiner oder gleich "y" ist. |
x > i | Wahr, wenn "x" grösser als "y" ist. |
x >= i | Wahr, wenn "x" grösser oder gleich "y" ist. |
x == i | Wahr, wenn "x" gleich "y" ist. |
x != i | Wahr, wenn "x" nicht gleich "y" ist. |
x ~ i | Wahr, wenn die Zeichenkette "x" mit dem durch "y" bezeichneten regulären Ausdruck übereinstimmt. |
x !~ i | Wahr, wenn die Zeichenkette "x" nicht mit dem durch "y" bezeichneten regulären Ausdruck übereinstimmt. |
unterskript in arrayi | Wahr, wenn das Array "array" ein Element mit den Unterskript "unterskript" hat. |
Vergleichsausdrücke haben den Wert "1" wenn wahr und "0" wenn falsch. Beim Vergleichen von Operanden gemischten Typs werden numerische Operanden in Zeichenketten verwandelt, wobei der Wert der Variable "CONVFMT" verwendet wird.
Zeichenketten werden verglichen, indem das erste Zeichen jeder Zeichenkette miteinander verglichen wird, danach das zweite usw. Die Zeichenkette "10" ist also weniger als "9". Gibt es zwei Zeichenketten bei der die eine der Vorspann der anderen ist, so ist die kürzere weniger als die längere. Die Zeichenkette "abc" ist also weniger als "abcd".
Oft wird der Fehler gemacht, dass anstatt "==" bloss "=" geschrieben wird. Das Ergebnis ist zwar gültiger awk-Code, liefert aber nicht das Gewünschte. Im folgenden Beispiel wird der "if"-Teil immer erfolgreich sein, ausser "b" hat den Wert "0" oder "".
if (a = b) # sollte eigentlich a == b heissen ... else ...
Die folgende Liste illustriert die Art der von gawk durchgeführten Vergleiche und zeigt die entsprechenden Ergebnisse.
1.5 <= 2.0 | Numerischer Vergleich (true). |
"abc" >= "xyz" | Zeichenkettenvergleich (false). |
1.5 != " +2" | Zeichenkettenvergleich (true). |
"1e2" < "3" | Zeichenkettenvergleich (true). |
a = 2; b = 2; a == b | Zeichenkettenvergleich (true). |
a = 2; b = " +2"; a == b | Zeichenkettenvergleich (false). |
Im folgenden Beispiel ist das Ergebnis "false", weil sowohl "$1" und "$2" Benutzereingaben sind. Sie sind numerische Zeichenketten und haben also das Attribut "strnum", was einen numerischen Vergleich erzwingt.
$ echo 1e2 3 | awk '{ print ($1 < $2) ? true "true" : "false" }' false
Der Zweck der Vergleichregeln und des Gebrauchs numerischer Zeichenketten ist der Versuch, ein "weniger überraschendes" Verhalten zu erzeugen, während immer noch "das richtige" gemacht wird. Zeichenkettenvergleiche und der Vergleich regulärer Ausdrücke sind sehr unterschiedlich. Das folgenden Beispiel hat den Wert "1" oder ist wahr, falls die Variable "x" genau "foo" entspricht.
x == "foo"
Im Unterschied dazu hat das nächste Beispiel den Wert "1", falls die Variable "x" den Wert "fuu" enthält, z. B. in der Zeichenkette "Oh, was für ein fuul ich bin!"
x ~ /foo/
Der rechtsseitige Operand der Operatoren "~" und "!~" kann entweder eine regexp-Konstante ("/.../") oder ein gewöhnlicher Ausdruck sein. Im letzteren Fall wird der Wert des Ausdruck als Zeichenkette als dynamischer regulärer Ausdruck verwendet.
In neueren Implementationen von awk ist eine regexp-Konstante in Schrägstrichen auch eine Ausdruck. Der reguläre Ausdruck "/regexp/" ist eine Abkürzung für folgenden Vergleichsausdruck:
$0 ~ /regexp/
"foo" ist aber dann keine Abkürzung für "$0 ~ /foo/", wenn es der rechtsseitige Operator von "~" oder "~!" ist.
Boolesche Ausdrücke
Eine Boolescher Ausdruck (auch: logischer Ausdruck) ist eine Kombination von Vergleichsausdrücken oder Übereinstimmungsausdrücken unter Verwendung der Booleschen Operatoren "oder" ("or" bzw. "||"), "und" ("and" bzw. "&&") und "nicht" ("not" bzw. "!") zusammen mit Klammern zur Steuerung von Verschachtelungen. Der Wahrheitswert des Booleschen Ausdrucks wird durch die Kombination der Wahrheitswerte der Komponentenausdrücke berechnet.
Boolesche Ausdrücke können überall da verwendet werden, wo Vergleichs- oder Übereinstimmunsgausdrücke eingesetzt werden können. Sie können in "if"-, "while"-, "do"- und "for"-Anweisungen verwendet werden. Sie haben numerische Werte ("1" wenn wahr, "0" wenn falsch), die ins Spiel kommen, wenn das Ergebnis des Booleschen Ausdrucks in einer Variable gespeichert oder zum Rechnen verwendet wird.
Zusätzlich ist jeder Boolesche Ausdruck auch ein gültiges Muster, sodass er as Muster zur Steuerung der Ausführung von Regeln benutzt werden kann. Die Booleschen Operatoren sind:
boolean1 && boolean2 | Wahr, wenn sowohl "boolean1" wie "boolean2" wahr sind. Die folgende Anweisung gibt den aktuellen Eingabsatz aus, falls er sowohl "2400" als auch "foo" enthält.
if ($0 ~ /2400/ && $0 ~ /foo/ print Der Unterausdruck "boolean2" wird nur berechnet, falls "boolean2" wahr ist. Das kann einen Unterschied machen, wenn "boolean2" Ausdrücke mit Nebenwirkungen enthält. Im folgenden Beispiel wird die Variable "bar" nicht um den Wert "1" erhöht, falls es keine Unterzeichenkette "foo" im Datensatz gibt. $0 ~ /foo/ && ($2 == bar++) |
boolean1 || boolean2 | Wahr, wenn mindestens einer von "boolean1" oder "boolean2" wahr ist. Die folgende Anweisung gibt alle Datensätze der Eingabe aus, die entweder "2400" oder "foo" oder beide enthalten.
if ($0 ~ /2400/ || $0 ~ /foo/ print Der Unterausdruck "boolean2" wird nur berechnet, wenn "boolean2" falsch ist. Das kann einen Unterschied machen, wenn "boolean2" Ausdrücke mit Nebenwirkungen enthält. |
! boolean | Wahr, wenn "boolean" falsch ist. Das folgende Programme gibt "Keine Heimat!" aus, falls die Variable "HOME" nicht belegt sein sollte.
BEGIN { if (! ("HOME" in ENVIRON)) print "Keine Heimat!" } |
Die Operatoren "&&" und "||" werden wegen der Art ihrer Arbeitsweise auch Kurzschlussoperatoren genannt. Die Auswertung des gesamten Ausdrucks wird "kurzgeschlossen", falls das Ergebnis bereits nach einem Teil der Auswertung feststeht.
Anweisungen, die "&&" oder "||" verwenden können durch einfaches Zufügen eines Zeilenumbruchs fortgesetzt werden. Hingegen darf kein Zeilenumbruch vor einem dieser Operatoren stehen, ohne dass die Fortsetzung mit umgekehrtem Schrägstrich verwendet würde.