Zitat von Kai
Mal 'nen ganz kurzer Überblick über Regexps:
Ein regulärer Ausdruck (so wie er in Ruby ist, der mathematische Hintergrund ist ja nochmal was ganz anderes) ist ein Muster für Strings. Eine Art Schablone, in die mehrere Strings reinpassen. Er baut sich aus folgenden Elementen zusammen:
- Terminale: Du kannst in einen Regexp ganz normale Zeichen reinsetzen, solange sie nicht schon für was anderes reserviert sind (in diesem Fall kannst du sie escapen, in dem du ein \ davorsetzt). zB. passt der Regexp /Hallo Welt/ genau auf den String "Hallo Welt". Der Regexp /Hallo\/Welt/ passt auf den String "Hallo/Welt". Das / muss hier escaped werden, weil es ja eigentlich das Trennzeichen für Regexps darstellt
- Gruppierung: Mit Klammern kannst du innerhalb eines regulären Ausdrucks einen Unterausdruck gruppieren. Auf diese Weise wirkt er im Grunde genommen wie ein Terminal. Bsp: /Hallo (Welt)/. Hier wurde Welt gruppiert. Wozu das genau dient, später.
- Wiederholungen: Mit {a, b} kannst du sagen, dass der letzte Ausdruck (Terminal oder Gruppierung) um mindestens a mal und maximal b mal wiederholt werden muss. /Hallo (Welt){2, 4}/ passt also auf die Strings "Hallo WeltWelt", "Hallo WeltWeltWelt" und "Hallo WeltWeltWeltWelt". Lässt du a weg, so wird für a automatisch 0 eingesetzt. Lässt du b weg, so wird automatisch unendlich dazu eingesetzt. /Hallo{,2}/ passt also zu "Hall", "Hallo", "Halloo".
- Alternation: Mit Alternation kannst du sagen, dass entweder der eine, oder der andere Ausdruck vorkommen muss. Man setzt Alternation mit |. Alternation beziehen sich nicht nur auf ein Terminal. Deswegen musst du sie selbst gruppieren.
/Hallo (Welt|Wald)/ passt auf "Hallo Welt" und "Hallo Wald"
- Zeichengruppen: Eine Gruppe ist nur eine Form der Alternation einzelner Terminale. Du kannst statt (a|b|c|d|e) auch eine Gruppe [abcde] schreiben. Beides ist äquivalent. Gruppen kennen zudem noch den Bindestrich Operator, mit dem du hintereinanderkommende Zeichen mit einbeziehen kannst: /[e-h]/ passt auf die Strings "e", "f", "g", "h". /[A-z]/ passt auf jeden Buchstaben. Weiterhin kannst du am Anfang einer Gruppe das ^ Zeichen setzen. Dann wird das Komplement der Gruppe gebildet. [^0-9] passt also auf alles, nur nicht auf "0", "1", "2", ..., "9".
- Weiterhin gibt es noch verschiedene vordefinierte Macros. + ist dasselbe wie {1,}. * ist dasselbe wie {0,}. ? ist dasselbe wie {0,1}.
/Hallo(Welt)?/ passt auf "Hallo" und "HalloWelt". /Hallo du+/ passt auf "Hallo du", "Hallo duu", "Hallo duuu", ...
\d ist dasselbe wie [0-9]. \D ist dasselbe wie [^0-9]. \s ist die Gruppe aller Leerzeichen (Neue Zeile, Tab, Leerzeichen usw.). \S ist wieder das Komplement davon. \w sind alle Buchstaben und Zahlen. \W ist das Komplement. Der einfache . Punkt ist die Gruppe ALLER Zeichen (außer Newline)
- Es gibt noch ein paar Optionen für Regexps. Die zwei wichtigsten:
i = case insensitiv. Wenn diese Option gesetzt ist, ist Groß- und Kleinschreibung egal. /a/ matcht dann also sowohl "A" als auch "a"
m = multiline-Mod. Wenn diese Option gesetzt ist zählt das Newline-Zeichen mit in die Gruppe von .
x = Hier zählen Leerzeichen und Kommentare (fangen mit # an) nicht als Terminale. Auf diese Weise kannst du deinen Regexp über mehrere Zeilen spannen und hübscher aufschreiben. Echte Leerzeichen musst du dann mit dem Escapezeichen "\ " kennzeichen
Optionen setzt man ans Ende des Regexps-Literals.
/Hallo ./cm =~ "hallo \n wie geht es dir?" #=> 0
/(\d+) # hier kommen Zahlen
\ Jahre \ alt # dieser Text soll danach kommen/x =~ "Ich bin 7 Jahre alt" #=> 8
Die vollständige Liste findest du in der Helpdatei des Makers.
- Dann gibt es noch einige weitere Kniffe (Anker, Greedy, usw.). Darauf will ich erstmal nicht eingehen. Auch hier: Guck in die Helpdatei.
- Jede Gruppierung bekommt, nach ihrem Auftreten, eine Nummer. /(Hallo (wie)) (gehts)/ hier gibt es drei Gruppen. (Hallo wie) ist Gruppe 1. (wie) ist Gruppe 2. (gehts) ist Gruppe 3. Wenn du einen Regexp auf einen String anwendest, wird versucht den String in die Regexp-Schablone reinzustecken. Dabei wird der Inhalt der Gruppen in den globalen Variablen $1, $2, $3, ... abgespeichert.
/Ich bin (\d+) Jahre alt/ =~ "Ich bin 20 Jahre alt"
p $1 #=> "20"
/Um (\d\d):(\d\d) Uhr/ =~ "Um 17:30 Uhr"
p $1 #=> "17"
p $2 #=> 30
...