Dies hier ist eine kleine Anleitung, um das scheinbare Geheimnis von StringRegExp() zu enträtseln.
StringRegExp(
"test",
"pattern" [,
flag ] )
"test" = Die Zeichenkette, die nach Treffern durchsucht werden soll.
"pattern" = Eine Zeichenkette, bestehend aus bestimmten Schlüsselzeichen, der die Funktion genau wissen lässt was gesucht wird. Kein wenn und aber, es gibt einen Treffer oder es gibt keinen.
flag[optional] = Sagt der Funktion ob nur nach dem pattern gesucht werden soll, oder ob nur der erste Treffer aus der test-Zeichenkette zurückgegeben wird oder alle.
Beispiel 1
MsgBox(0, "SRE Beispiel 1 - Ergebnis", StringRegExp("text", 'test'))
In diesem Beispiel, sollte die MessageBox "0" ausgeben, was
bedeutet, das Suchmuster "test" wurde in der zu testenden Zeichenkette
"text" nicht gefunden. Ich weiß, dies erscheint kinderleicht, aber
jetzt wissen wir wenigstens auch warum "test" nicht gefunden wurde.
Um als nächstes ein Suchmuster festzulegen, nutzen wir eine
Zeichenklasse ("[ ... ]"). Die Abgleichung der Zeichenmuster in
Zeichenklassen können wir uns wie das logische "OR" vorstellen. Nehmen
wir wieder das vorherige Beispiel. Wir wollen entweder die Zeichenkette
"test" oder "text" finden. Nun, die Art wie ich beginne nach einem
Suchmuster Ausschau zu halten, ist so zu denken wie SRE es auch tun
würde: Das erste abzugleichende Zeichen ist "t", dann der Buchstabe
"e", dies gilt bis jetzt für beide Suchmuster. Jetzt möchten wir ein
"s" OR "x", demnach können wir eine Zeichenklasse als Ersatz nutzen
für: "[sx]" bedeutet, suche nach einer Übereinstimmung mit einem "s"
oder einem "x". Der letzte Buchstabe ist nun wieder ein "t", was auch
wieder für beide Suchmuster gilt.
Beispiel 2
MsgBox(0, "SRE Beispiel 2 - Ergebnis", StringRegExp("text", 'te[sx]t'))
MsgBox(0, "SRE Beispiel 2 - Ergebnis", StringRegExp("test", 'te[sx]t'))
Beide Aufrufe von SRE sollten zu dem Ergebnis "1" führen, denn das Suchmuster sollte eine Übereinstimmung
in beiden Fällen "test" und "text" ergeben.
Es kann außerdem festgelegt werden, wie oft jedes Zeichen übereinstimmen soll, indem man "{Anzahl
der Übereinstimmungen}" dem Zeichen anfügt oder man legt einen Bereich "{min, max}" fest. Das erste
Beispiel weiter unten ist eigentlich überflüssig, aber zeigt was ich meine:
Beispiel 3
MsgBox(0, "SRE Beispiel 3 - Ergebnis", StringRegExp("text", 't{1}e{1}[sx]{1}t{1}'))
MsgBox(0, "SRE Beispiel 3 - Ergebnis", StringRegExp("aaaabbbbcccc", 'b{4}'))
$asResult = StringRegExp("Dies ist ein Test-Beispiel", '(Test)', 1)
If @error == 0 Then
MsgBox(0, "SRE Beispiel 4 - Ergebnis", $asResult[0])
EndIf
$asResult = StringRegExp("Dies ist ein Test-Beispiel", '(Te)(st)', 1)
If @error == 0 Then
MsgBox(0, "SRE Beispiel 4 - Ergebnis", $asResult[0] & "," & $asResult[1])
EndIf
So, als erstes muss das Suchmuster in der zu testenden Zeichenkette eine Übereinstimmung finden. Ist dies der Fall,
dann wird SRE mitgeteilt jegliche Gruppen ("()")"einzufangen" und sie in dem zurückzugebenden Array
abzulegen. Es können mehrfache Gruppen verwendet werden, wie im zweiten Teil des Beispielcodes.
Ok, zurück zum knorrigen Monster. Jetzt, wo wir wissen wie man Text
"einfängt", lasst uns das Suchmuster zusammensetzen: Seitdem wir
wissen, dass wir Zahlen suchen, bieten sich uns 3 Wege an für "Finde
eine Zahl": "[:digit:]", "[0-9]", und "\d". Das erste ist vermutlich am
einfachsten zu verstehen. Es gibt ein paar Klassen (digit, alnum,
space, etc. siehe in der Hilfedatei für eine vollständige Liste) die
wir nutzen können um Zeichenklassen festzulegen, eine von ihnen ist für
Zahlen. "[0-9]" legt lediglich einen Bereich aller Zahlen zwischen 0
und 9 fest. "\d" ist bloß ein Sonderzeichen mit der gleichen Bedeutung
wie die ersten beiden Arten. Zwischen den dreien besteht kein
Unterschied, und mit allen SRE's gibt es wenigstens ein paar Wege um
irgendein Suchmuster zusammenzusetzen.
Nun, das erste was wir wissen ist, dass wir die Zahlen(-gruppe) einfangen wollen, also weisen wir daraufhin
indem wir eine Klammer öffnen "(". Als nächstes wissen wir, dass wir zwischen 1 und 3
Zeichen einfangen wollen, alle aus Zahlen bestehend, sodass unser Suchmuster jetzt aussieht wie
"([0-9]{1,3}". Und letztendlich schließen wir das ganze mit einer Klammer um auf das Ende
der Gruppe hinzuweisen: "([0-9]{1,3})". Lasst es uns ausprobieren:
Beispiel 5
$asResult = StringRegExp("Knorriges Monster schlägt dich und fügt dir 18 Schadenspunkte zu.",
_
'([0-9]{1,3})', 1)
If @error == 0 Then
MsgBox(0, "SRE Beispiel 5 - Ergebnis", $asResult[0])
EndIf
Na bitte, die MessageBox zeigt korrekt "18" an.
Als
nächstes schauen wir uns die nicht-einfangenden Gruppen an. Die Art wie
wir diese Gruppen kenntlich machen ist "(?:" anstatt nur "(". Lasst uns
annehmen euer Log sagt "Du konntest 36 von Knorriges Monster 279
Schadenspunkte ausweichen.". Wenn wir nun Beispiel 5 ausführen, erhalten
wir "36" anstatt "279". Nun möchte ich an dieser Stelle den Unterschied
der beiden Zahlen untersuchen. Das erste was mir auffällt ist, dass der
zweiten Zahl immer ein Leerzeichen folgt und dann das Wort
"Schadenspunkte". Wir könnten nun unser voriges Suchmuster abändern zu
"([0-9]{1,3} Schadenspunkte)", aber was ist wenn unser Skript nur nach
der Menge der Schadenspunkte sucht, ohne "Schadenspunkte" an das Ende der
Zahl anzuheften? An dieser Stelle können wir nicht-einfangende Gruppen
einsetzen um unser Ziel zu erreichen.
Beispiel 6
$asResult = StringRegExp("Du konntest 36 von Knorriges Monster 279 Schadenspunkte ausweichen.",
'([0-9]{1,3})(?: Schadenspunkte)', 1)
If @error == 0 Then
MsgBox(0, "SRE Beispiel 6 - Ergebnis", $asResult[0])
EndIf
Dieses Thema könnten wir noch weiter ausdehnen, aber Zielsetzung dieses Tutorials ist die Grundlagen
zu vermitteln, wie reguläre Ausdrücke funktionieren und hauptsächlich wie SRE "denkt". Hier noch einige Sachen
die man im Hinterkopf behalten sollte:
- Nicht vergessen über das Suchmuster für jedes Zeichen nachzudenken
- Die StringRegExp() Funktion findet das erste Zeichen in dem
Suchmuster, danach ist es dein Job genügend Belege zu erbringen um zu
"Beweisen" ob oder ob keine Übereinstimmung erfolgt. Beispiel 6 ist ein
gutes Beispiel dafür.
- Nicht vergessen, [ ... ] bedeutet OR ([xyz] finde ein "x", ein "y", oder ein "z")
Sollten noch Fragen offen sein, sollte der erste Griff zur Hilfedatei sein! Diese erklärt im Detail
die wesentliche Syntax, die mit SRE daherkommt. Eine Sache
auf die man ein besonderes Augenmerk legen sollte ist die Sektion über "Wiederkehrende Zeichen".
Dies macht das Suchmuster leichter lesbar, wenn man für bestimmte Zeichen Bereiche festlegt. Zum
Beispiel: "*" ist gleichbedeutend mit {0,} oder dem Bereich von 0 bis irgendeine Anzahl von Zeichen.
Viel Glück, Reguläre Ausdrücke können großartig dazu genutzt werden um die Länge des Codes zu reduzieren,
und machen eine spätere Änderung dessen wesentlich einfacher. Korrekturen und Resonanz sind stets willkommen!
The 30 Minute Regex Tutorial - von Jim Hollenhorst.
GUI um verschiedene Suchmuster mit StringRegExp() zu testen -
Vielen Dank an steve8tch. Anerkennung: w0uter
Vielen Dank an neogia für dieses Tutorial.