Edit v4.000 from 2019-11-20 to 2019-11-25 by TSc
Grundlagen (der kleinste, gemeinsame Nenner)
In die Welt der regulären Ausdrücke hereinzukommen,
ist alles andere als leicht.
Es gibt zwar sehr viele Anleitungen im Internet dafür,
aber meistens sind diese sehr dürftig umgesetzt,
oder zu komplex beschrieben.
Dann kommt noch dazu,
dass es sehr viele verschiedene Arten von Implementationen gibt.
Das bedeutet man kann das neu gelernte nicht wirklich anwenden,
weil die Implementation,
wo man das gelernte einsetzen will,
das gelernte nicht voll unterstützt oder
etwas ganz anderes dabei herauskommt,
als man erwartet.
Auf dieser Seite versuchen wir,
ihnen zu erklären was reguläre Ausdrücke sind,
wie diese kryptischen Zeichenfolgen zu interpretieren sind und
eine Beschreibung aller Steuerzeichen ,
um damit von Grund auf einen eigenen regulären Ausdruck bilden zu
können.
Wir beschränken uns dabei auch nur auf die Möglichkeiten,
die in so gut wie allen Implementationen funktionieren.
Anmerkung:
Aktuell gibt rund 20 verschiedene Implementationen,
wovon einige sogar so exotisch sind,
das dass hier gezeigte nicht ohne weiteres funktioniert.
Die Zeichenfolgen der regulären Ausdrücke spalten sich prinzipiell
in 2 Arten auf:
- Klartext und
- Steuerzeichen.
Die Steuerzeichen selbst werden mit Symbolen wie Klammern und
mathematischen Zeichen beschrieben.
Diese dienen zur Beschreibung eines Suchmuster.
Das bedeutet somit auch,
wenn man als Suchmuster nur Klartext angibt,
dann funktioniert das Suchmuster auch genauso wie eine Klartextsuche.
Hat man allerdings im Text auch Symbole dabei,
die als Steuerzeichen für die regulären Ausdrücke verwendet
werden,
dann muss man diese Escapen ,
d.h. man muss dem jeweiligen Symbol meistens dann ein
\ -Symbol (Backslash) voranstellen.
Gehen wir nun mal auf die Steuerzeichen ein,
die sind das was die regulären Ausdrücke so mächtig machen,
bzw. auch so kryptisch.
Davon gibt es nicht mal so viele.
Zu wissen wofür sie da sind ist aber fundamental für das
Verständnis.
Zuerst Liste ich diese erst einmal auf,
mit einer Beschreibung was sie tun und
einem kurzen abstrakten Beispiel dazu.
Das, was es so komplex macht sind auch nicht die einzelnen Bedeutungen der
Steuersymbole an sich,
sondern die Kombination derer.
- ^
-
Mit dem Zirkumflex fixiert man den Anfang einer Zeichenkette,
bzw. den Anfang einer Zeile.
So bedeutet z.B.
^abc das nur Muster erkannt werden,
die in einer Zeile/Zeichenkette mit abc
beginnen.
- $
-
Mit dem Dollar-Zeichen fixiert man das Ende einer Zeichenkette,
bzw. das Ende einer Zeile.
So bedeutet z.B.
abc$ das nur Muster erkannt werden,
die in einer Zeile/Zeichenkette mit abc
enden.
- .
-
Der Punkt ist eine sogenannte Zeichenauswahl.
Das bedeutet,
der Punkt steht für alle druckbaren Zeichen.
Das Zeichen kann man auch wie in einem Kartenspiel als Joker sehen und
wird deshalb auch oft
Wildcard genannt.
Welche Zeichen genau dem Punkt zugeordnet sind,
kann sich je nach Implementation unterscheiden.
Wenn man z.B. in einem Text nach . sucht,
findet es quasi jedes druckbare Zeichen und zwar immer
eins davon.
Wenn man nach einem Punkt selbst sucht,
muss dieser logischerweise Escaped werden,
also \. .
- +
-
Das Plus-Zeichen ist eine Längenbeschreibung,
die man z.B. dem Punkt anhängen kann und bedeutet:
Finde mindestens
1 oder mehr Zeichen.
Das heißt z.B. wenn man nach
.+ sucht,
dann findet man alles was mindestens ein Zeichen lang ist.
Das Plus-Zeichen bezieht sich stets auf den voran gegangenen Ausdruck.
Zur Verständlichkeit ein weiteres Beispiel.
Wenn man nach a+ sucht,
dann findet man alles was alles was mindestens ein a ist und
somit auch aa , aaa , usw.
- *
-
Das Stern-Zeichen ist dem Plus-Zeichen sehr ähnlich und bedeutet:
Finde mindestens 0 oder mehr Zeichen.
Das Stern-Zeichen bezieht sich stets auf den voran gegangenen Ausdruck.
Wenn man das zweite Beispiel vom Plus-Zeichen wieder nimmt,
aber stattdessen nach
a* ist das Ergebnis das selbe,
allerdings zählt auch nichts als Suchtreffer.
- ?
-
Mit dem Fragezeichen kann man bestimmen,
ob der vorangegangene Ausdruck optional ist.
Zum Beispiel könnte man damit testen,
ob ein URI-Schema
http und/oder https ist.
Das heißt,
wenn man nach https?:// sucht,
dann findet man sowohl http:// ,
als auch https:// .
Das funktioniert deshalb,
weil man angegeben hat,
das der Buchstabe s optional ist.
- |
-
Der senkrechte Strich ist eine Oder-Anweisung.
Wenn man z.B. nach
a|b sucht,
dann findet man alles, was entweder ein a
oder ein b ist.
Besonders mit den runden Klammern ist dieses Zeichen sehr nützlich,
weil man damit z.B. eine Liste gültiger Wörter beschreiben
kann.
- ()
-
Mit den runden Klammern kann man Gruppen beschreiben,
welche dann z.B. im Ersetzungsmuster platziert werden können,
oder auch um eine längere Zeichenkette als optional zu beschreiben.
Bei den runden Klammern fängt es auch an richtig komplex zu werden.
Als Beispiel nehmen wir mal das,
was wir schon vom senkrechten Strich wissen.
Wir suchen nach
(der|die|das) und finden alle Wörter,
die entweder der , die , oder das
enthalten.
Zusätzlich,
wenn man ein Ersetzungsmuster benutzt,
wird der erkannte Inhalt in der Klammer zu dem Platzhalter
$1 bzw. \1 gepackt.
Das heißt,
wenn man z.B. die gefunden hat,
dann enthält auch $1 bzw.
\1 im Ersetzungsmuster das Wort
die .
- []
-
Die eckigen Klammern sind die Zeichenauswahl,
das bedeutet,
alles was man in die eckigen Klammern schreibt,
kann an dieser Zeichenposition gefunden werden.
So bedeutet z.B.
[0123456789] finde eine Zahl zwischen 0 und
9.
Da dies vor allem beim Alphabet dann richtig lang wird,
kann man auch einen Bereich mittels dem - -Zeichen definieren.
So bekommt man genau den selben Ausdruck viel kürzer hin:
[0-9] .
Die Bereiche orientieren sich nach der Ordnung in der ASCII-Tabelle und
ist optimal für Zahlen, Großbuchstaben und Kleinbuchstaben,
jedoch nicht auf diese beschränkt.
Wichtig bei dieser Zeichenauswahl ist auch,
das diese sich immer auf eine Zeichenposition bezieht,
das bedeutet,
sucht man nach beliebig großen Zahlen,
könnte man es mit einer Längenbeschreibung erweitern.
Wenn wir also nach [0-9]+ suchen,
dann finden wir beliebig große Ganzzahlen,
wo aber auch Nullen vorangestellt sein könnten.
- {}
-
Mit den geschweiften Klammern kann man eine Längenbeschreibung
exakt definieren,
was sehr hilfreich ist,
wenn das Plus-Zeichen,
oder das Stern-Zeichen nicht ausreicht.
Auch diese Längenbeschreibung bezieht sich stets auf den voran
gegangenen Ausdruck.
Im Prinzip gibt 2Ausdrucksweisen,
wie man eine Längenbeschreibung definieren kann.
Dabei kommt es drauf an welche Regeln gelten sollen.
Hier eine kurze Auflistung,
wie man mit der Längenbeschreibung arbeitet:
- Exakte Länge, z.B.
{2} = genau 2 lang.
-
Mindestlänge, z.B.
{1,} =
mindestens 1 lang, maximal beliebig.
-
Maximallänge, z.B.
{0,3} =
mindestens 0 lang, maximal 3 lang.
Wie man sehen kann,
ist der Maximalwert bei der Mindestlänge nicht beschrieben,
das Komma aber gesetzt.
Und bei der Maximallänge ist als mindestens eine 0 beschrieben,
da der Ausdruck {,3} ungültig wäre.
Wenn man darüber nachdenkt,
merkt man auch schnell,
wie das Plus-Zeichen und
das Stern-Zeichen in dieser Längenbeschreibung zu sehen sind:
Wenn wir also jetzt wieder unser Beispiel mit den Ganzzahlen nehmen,
können wir nun genau bestimmen wie lang diese sein sollen.
Als Beispiel, nehmen wir eine beliebige Zahl zwischen 0-9999,
also suchen wir nach [0-9]{1,4} .
Wichtig dabei ist,
auch wenn wir damit Zahlen finden wollen,
ist dies im Kontext einer Zeichenkette,
d.h. dieser Ausdruck findet auch Zahlen wie
0099 .
Wenn man sehr explizit einen Zahlenraum beschreiben möchte,
ist dies ein durchaus komplexer Ausdruck.
Nehmen wir mal als Beispiel den Zahlenraum 1-10 ,
da würde der Ausdruck in etwa so aussehen:
([1-9]|10) .
Für solche Fälle gibt es aber auch Werkzeuge im Internet,
die einem reguläre Ausdrücke für Zahlenbereiche automatisch
erzeugen können.
- \
-
Der Backslash wird als sogenanntes
Escape -Symbol verwendet.
Das bedeutet im Grunde genommen,
das man z.B. nach dem Zeichen nach dem Backslash selbst sucht und
dieser nicht als Steuersymbol ausgewertet werden soll.
Wenn man also nach einem Plus-Zeichen im Text sucht,
schreibe man \+ .
Eine weitere Funktion für das Backslash ist die Beschreibung
von Sonderzeichen (auch Metacharakter genannt), also
\\ = Ein Backslash selbst (\ )
-
\b = Wortbündel
(spezifiziert ganzes Wort, z.B. \bKatze )
-
\B = Die Umkehrung vom ganzen Wort,
also nicht Anfang oder Ende vom Wort.
-
\d = Alle Zahlen
\D = Alles außer Zahlen
\f = Form feed
\n = Line Feed
-
\s = Whitespaces ,
also mindestens Leerzeichen und Tabulator.
Bei vielen Implementationen auch
\f , \n , \r und \t .
-
\S = Alles außer \s
\r = Carriage Return
\t = nur Tabulatoren
\w = Alle Buchstaben, Zahlen und _
-
\W = Alles außer \w selbst.
Dies sind normale Sonderzeichzen aus der ASCII-Tabelle,
jedoch gibt es noch weitere,
welche mit Buchstaben definiert werden.
In der Regel sind dies dann weitere Gruppierungen von bestimmen
Zeichengruppen.
So ist wie in der Liste das \s ein Gruppensymbol
für nicht sichtbare, aber druckbare Zeichen,
also Leerzeichen und Tabulator.
Und das war noch nicht mal alles,
es gibt auch eine nummerische Schreibweise,
um beliebige Zeichen in der jeweiligen Zeichenkodierung ansprechen zu
können.
Dies ist vor allem bei UTF-8 und Bytefolgen sehr hilfreich.
Folgende Schreibweisen sind möglich:
-
\nnn = Oktale Schreibweise
(n = Zahl zwischen 0 und 8; Maximal 3 Stellen lang)
-
\xhh = Hexadezimale Schreibweise
(h = Zahl zwischen 0 und F; Nur zweistellig)
-
\uhhhhhhhh = Unicode-Schreibweise
(h = Zahl zwischen 0 und F;
zweistellig, vierstellig und achtstellig möglich)
Mit dem hier erlangten Wissen sollte man nun in der Lage sein,
selbst reguläre Ausdrücke erstellen zu können.
Nun folgt noch ein Beispiel,
was viele der Symbole kombiniert verwendet.
Aufgabe
Nehmen wir mal an wir haben immer einen Satz der so aufgebaut ist:
Ich habe gestern 50,00 Euro bezahlt. .
Nun wollen wir aber auch ähnliche Sätze mit einem einzigen
Suchmuster erkennen können,
also die Währung sollte auch Dollar können,
der Satz muss in einer Zeile/Zeichenkette beginnen und enden,
der Betrag sollte beliebig groß sein können,
der Ausdruck gestern sollte auch stattdessen heute sein
können und
bezahlt kann stattdessen auch geliehen sein.
Der regulären Ausdruck selbst wird in einer Akkordeon-Box versteckt,
als mögliche Lösung für diese Aufgabe.
Nun noch eine Liste von Beispielsätzen,
wo dieser reguläre Ausdruck funktionieren sollte:
Ich habe gestern 50,00 Euro bezahlt.
Ich habe gestern 53,67 Euro geliehen.
Ich habe heute 2 Dollar geliehen.
Ich habe heute 413,25 Dollar bezahlt.
Lösung
^Ich habe (gestern|heute) ([0-9]+(,[0-9]{2})?) (Euro|Dollar) (bezahlt|geliehen)\.$
|