Wortfetzen
Teil 3: String-Verarbeitung und Reguläre Ausdrücke
Reguläre Ausdrücke
Es gibt noch einen dritten Weg, wie wir den Dateinamen vom Verzeichnis trennen können, mittels regulären Ausdrücken:
#!/bin/bash
Datei="${1//#*\//}"
Verzeichnis="${1/%\/[^\/]//}"
echo Verzeichnis: $Verzeichnis
echo Datei: $DateiDie zweite Zeile ist die gierige Version des "Suchen/Ersetzen"-Befehls, allgemein beschrieben lautet er ${variable//suchmuster/ersetzung}. Unser Suchmuster ist "#*\/", was auf den ersten Blick kompliziert wirkt. Die Raute am Anfang bedeutet, dass das nachfolgende Muster am Anfang der Variable vorkommen muss. Der Stern steht für eine beliebige Zeichenfolge, und "\/" ist nichts anderes als ein geschützter Slash – sonst würde er als Beginn der Ersetzung fehlgedeutet.
Effektiv ist das Suchmuster also "#*/", eine beliebige Zeichenkette gefolgt von einem Schrägstrich, die am Anfang der Variablen stehen muss. Da es sich um die gierige Version des Befehls handelt, nimmt er bei "/usr/X11R6/bin/X" die Zeichenfolge "/usr/X11R6/bin/" unter Beschlag. Das gefundene Muster wird nun gegen die Ersetzung ausgetauscht – diese ist in unserem Falle leer (zwei aufeinander folgende Slashes), weshalb der passende Teil-String entfernt wird. Übrig bleibt "X", der Dateiname.
Die nächste Zeile besorgt uns das Verzeichnis. Gesucht wird nach dem Muster "%\/[^\/]", wobei auch hier die durch Backslashes geschützten Schrägstriche zu sehen sind – vereinfacht lautet das Suchmuster "%/[^/]". Das Prozent-Zeichen bedeutet, dass das nachfolgende Muster am Ende der Variablen stehen muss, um zu passen. In den eckigen Klammern steht eine Reihe von Zeichen, die alternativ vorkommen dürfen – [123] bedeutet, dass 1, 2 oder 3 an dieser Stelle passt. In unserem Fall stehen ein Dach und der Slash in den Klammern, doch das Dach selbst hat noch eine Sonderstellung. Steht es am Anfang, so dürfen die nachfolgend aufgelisteten Zeichen der Klammer nicht vorkommen. "[^/]" bedeutet somit alle Zeichen bis auf den Schrägstrich. Das ganze Muster zusammen trifft also eine Zeichenkette, die mit einem Slash beginnt, dann beliebige Zeichen (mit Ausnahme eines weiteren Schrägstrichs) enthält und insgesamt am Ende der Variablen steht.
Notwendig wird diese zugegebenermaßen wenig einleuchtende Schreibweise dadurch, dass bei Suchen/Ersetzen stets von vorn ausgewertet wird. Ein "/*" hätte in der dritten Zeile trotz Verwendung der genügsamen Methode "/usr/X11R6/bin/X" umfasst, als Ergebnis wäre ein leerer String übrig geblieben. Nur durch das Wissen, dass der Name des Programms hinter dem letzten Schrägstrich steht, er also beliebige Zeichen mit Ausnahme des Slash enthält, konnten wir diesen Fall durch Suchen/Ersetzen lösen.
Ich möchte nicht tiefer in die Thematik der regulären Ausdrücke eindringen. Dieses Gebiet ist so hoch komplex, dass sich ganze Bücher mit nichts anderem beschäftigen und selbst gestandene Programmierer bei manchen Ausdrücken nur hilflos mit den Schultern zucken. Für den Hausgebrauch reicht es völlig, mit Stern, Fragezeichen, eckigen Klammern und Dach umzugehen. Wer sich wirklich in die Welt der Muster einarbeiten will, dem sei das O'Reilly-Buch "Reguläre Ausdrücke" empfohlen.
Finale
Damit endet der dritte Teil des Programming Corners. Das Thema String-Verarbeitung haben wir nun abgehakt – Zeit, sich mit weniger staubigen Dingen zu beschäftigen. In der nächsten Folge werde ich deshalb mit den Kontrollstrukturen wie Bedingungen und Schleifen beginnen. Damit können wir dann sehr viel leistungsfähigere Programme gestalten.
Befehle zur String-Verarbeitung
| ${#variable} | Länge der variable in Zeichen. |
| ${variable:?string} | Gibt string aus, wenn variable leer ist oder nicht existiert. |
| ${variable:-string} | Ergebnis ist string, wenn variable leer ist oder nicht existiert, andernfalls wird variable zurückgegeben. |
| ${variable:=string} | string wird variable zugewiesen, wenn variable leer ist oder nicht existiert, andernfalls wird variable zurückgegeben. |
| ${variable:+string} | Ergebnis ist string, wenn variable existiert und nicht leer ist, andernfalls wird nichts zurückgegeben. |
| ${variable:offset} | Liefert den Inhalt von variable ab Position offset bis zum Ende. Ist variable ein Array, werden alle Elemente ab offset bis zum Ende des Arrays zurückgegeben. |
| ${variable:offset:länge} | Liefert länge Zeichen des Inhalts von variable ab Position offset. Ist variable ein Array, werden länge Elemente ab Element offset zurückgegeben. |
| ${variable:#muster} | Entfernt das kleinste zutreffende muster aus variable (genügsam). Sucht von vorn nach hinten. |
| ${variable:##muster} | Entfernt das größte zutreffende muster aus variable (gierig). Sucht von vorn nach hinten. |
| ${variable:%muster} | Entfernt das kleinste zutreffende muster aus variable (genügsam). Sucht von hinten nach vorn. |
| ${variable:%%muster} | Entfernt das größte zutreffende muster aus variable (gierig). Sucht von hinten nach vorn. |
| ${variable/muster} | Durchsucht variable von vorn nach hinten und entfernt das erste zutreffende muster. |
| ${variable//muster} | Durchsucht variable von vorn nach hinten und entfernt alle zutreffenden muster. |
| ${variable/muster/string} | Durchsucht variable von vorn nach hinten und ersetzt das erste zutreffende muster durch string. |
| ${variable//muster/string} | Durchsucht variable von vorn nach hinten und ersetzt alle zutreffenden muster durch string. |
Glossar
Substring
Teil einer Zeichenkette.
Offset
Verschiebung gegenüber dem Nullpunkt oder Anfang. Grundsätzlich kann es positive und negative Offsets geben, negative Werte werden vom Ende herunter gezählt.
positional parameters
In den Variablen $0, $1, $2 usw. werden alle Parameter eines Programmaufrufs einzeln gespeichert. Ihnen kann nichts direkt zugewiesen werden, lediglich mit set ist ein Neuladen möglich.
pattern matching
Mustervergleich, bei dem ein aus wildcards, Sonderzeichen und normalen Zeichen bestehendes Muster (pattern) mit einer Zeichenkette verglichen wird.
wildcards
Jokerzeichen, zum Beispiel Fragezeichen und Stern. Sie stehen für ein beliebiges Zeichen oder beliebig viele Zeichen. Mit ihnen lassen sich komplexe Muster und reguläre Ausdrücke bilden.
regulären Ausdrücken
Auch kurz "regex" oder regular expression genannt, ist der Oberbegriff für Muster. Mit einem regulären Ausdruck werden Textmuster beschrieben, beinahe wie in einer kleinen Programmiersprache. Dabei können reguläre Ausdrücke sowohl zum Suchen als auch Ersetzen von Textmustern verwendet werden.



