Suche mit regulären Ausdrücken (regex): Unterschied zwischen den Versionen

Aus m-wiki
Zur Navigation springen Zur Suche springen
 
(Eine dazwischenliegende Version desselben Benutzers wird nicht angezeigt)
Zeile 1: Zeile 1:
== Einführung ==
== Einführung ==
Die regulären Ausdrücke stehen in vielen Programmiersprachen zur Verfügung und ermöglichen eine komplexe Suche, da man Muster in Zeichenketten suchen kann im Gegensatz zu einer fixen Vorgabe.
Reguläre Ausdrücke stehen in vielen Programmiersprachen wie etwa [[Java]] oder [[PHP]] zur Verfügung und ermöglichen eine komplexe Suche, da man Muster in Zeichenketten suchen kann im Gegensatz zu einer fixen Vorgabe.


== Aufbau eines Suchmusters ==
== Aufbau eines Suchmusters ==

Aktuelle Version vom 26. Juli 2020, 22:59 Uhr

Einführung

Reguläre Ausdrücke stehen in vielen Programmiersprachen wie etwa Java oder PHP zur Verfügung und ermöglichen eine komplexe Suche, da man Muster in Zeichenketten suchen kann im Gegensatz zu einer fixen Vorgabe.

Aufbau eines Suchmusters

Sonderzeichen

Die folgenden Zeichen besitzen eine spezielle Bedeutung und müssen daher markiert werden, wenn man nach ihnen sucht. Entsprechend auch die Zeichen, welche gebraucht werden, um Suchkriterien zu bilden, wie etwa die Klammern.

Zeichen Bedeutung Beispiel Bemerkungen
\ Maskierzeichen \. Maskiert den Punkt, so dass dieser gesucht werden kann. Mit dem \ können auch Spezialzeichen aus dem tiefen ASCII-Satz gesucht werden.
- Bereichszeichen [5-9] Trennt den Stat- und Endpunkt eines Bereichs.
? Erweitert Klammern und die Greedy Funktion ? Neben der Anzahl möglicher Suchresultate modifiziert er die Suche und zwar ob die Suche nach einem Treffer abgebrochen werdne soll oder nicht und auch die Klammerfunktion wird damit erweitert.
^ Negation [^A] Wenn das Zeichen als erstes in einer Klasse (Aufzählung) erscheint, dann wird diese negiert.

Suchkriterien

Muster Bedeutung Beispiel Bemerkungen
[abc] Ein Zeichen der vordefinierten Liste a oder b oder c Der String darf nur die aufgezählten Zeichen anthalten und dies auch nur einmal.
[^abc] Kein Zeichen der vordefinierten Liste x oder z Negation. Die Zeichen dürfen nicht enthalten sein.
[b-h] Bereich von Kleinbuchstaben c oder f Ein beliebiger kleiner Buchstabe aus dem gegebenen Bereich. Wichtig. Es werden keine Umlaute usw. unterstützt. Für internationale Zeichen daher besser untenstehende Zeichen verwenden.
[a-zA-Z] Bereich von Klein- und Grossbuchstaben s oder K Ein kleiner oder grosser Buchstabe. Kann auch mit dem Modifikator i erreicht werden.
^ Zeilenanfang ^Müller Der Suchstring muss am Start stehen. Herr Müller wird in diesem Fall nicht gefunden.
$ Zeilenende Test$ Umkehrung von ^. Dies ist ein Test. -> Wird wegen dem . nicht gefunden.
. beliebiges Zeichen T..t Findet Tuut oder Test
() Alternativen oder Teilbereiche z|) weisse) (Karte|Katze)). Die Rückgabeliste von "die weisse Karte" wäre in diesem Fall 1 = weisse Karte, 2 = weisse und 3 = Karte
(a|b) Oder (Ich|Du|Er) Liste von Alternativen
? Kein oder einmalig a? Das Zeichen darf fehlen, doch maximal einmal auftreten. Ma?l -> Ml ergibt TRUE, Maal ergibt FALSE. Ist eine Kurzform von {0,1}.
* Beliebig oft *a Egal ob das Zeichen fehlt oder x-Mal vorkommt. Ma*l -> Ml, Mal, Maaal -> ergibt alles TRUE. Ist eine Kurzform von {0,}.
+ Mindestens einmal Ma+l Ml liefert hier FALSE, doch Mal und Maaal TRUE. Ist eine Kurzform von {1,}.
{2} Exakt x-Mal Me{2}r Nur Meer ergibt TRUE
{3,} Mindestens x-Mal Me{3,}t Nur ab 3 e (Meer, Meeeeer) ergibt es TRUE
{2,5} Bereich Me{2,5}r Von Meer bis Meeeeer ergibt TRUE, alles andere FALSE
\1 (Rück)verweis respons)e and \1ibility Findet "sense and sensibility" und "response and responsibility", aber nicht "sense and responsibility". Die Rückverweise beziehen sich auf die Klammern, gezählt von Links. Entsprechend kann man auch einen "Vorwärtsrückverweis" erstellen, der auf Daten rechts von der Abfrage verweist.
(?= (?! Vorwärtsbeziehung (?!foo)bar Wenn man = verwendet, so muss es sein und beim ! darf es nicht sein. In diesem Beispiel darf bar nicht auf foo folgen.
(?<= (?<! Rückbeziehung (?<=\d{3})(?<!999)foo Wenn man = verwendet, so muss es sein und beim ! darf es nicht sein. In diesem Beispiel werden zwei Rückbeziehungen gekoppelt. Die erste Anweisung erfordert 3 Zahlen vor foo und die zweite schränkt diese auf nicht 999 ein. 123foo ist TRUE und 999foo ist FALSE.

Suchklassen

Diese zeigen an, welche Zeichenklasse gesucht wird. Je nachdem müssen diese bei internationalen Suchtexten mit Metaklassen ergänzt/ersetzt werden.

Muster Bedeutung Beispiel Bemerkungen
\A Start des Strings \AHallo Das gesuchte Muster muss am Anfang des Suchstrings stehen. Im Gegensatz zu ^ gilt hier die Newline-Regel nicht.
\z Ende des Strings \zEnde Gegenteil von \A -> Suchmuster muss am Ende sein. Bei Multiline zählt daher nur die letzte Zeile.
\Z Ende des Strings oder der Zeile \zEnde Gegenteil von \A doch im Gegensatz zu \z findet man hier auch Wörter vor dem Zeilenumbruch. Ist somit wie der $ zu behandeln.
\s Jegliche Leerzeichen " " Neben dem Leerzeichen kann es auch ein Tab usw. sein.
\S Jegliches Zeichen, das kein Leerzeichen ist x Gegenteil von \s
\d Zahl 5 Für Hex muss man eine eigene Klasse definieren
\D Alle Zeichen, die keine Zahl sind A oder " " Gegnteil von \d
\w Schreibzeichen x oder 7 oder _ Nur für englische Schriften. Für internationale Zeichen die entsprechenden Klassen unten verwenden.
\W Nicht-Schreibzeichen " " Gegenteil von \w
\b Wortgrenze .*test\b Kann vor und hinter einem Begriff stehen und grenzt entsprechend ab, wenn der Begriff den Anfang und/oder das Ende eines Wortes anzeigen soll. Antesten liefert FALSE, während Grosstest TRUE liefert
\B Keine Wortgrenze .*test\B Gegenteil von \b
\G Position test\G Ist nur TRUE, wenn man bei der Suche einen Offset eingibt und die Suche dort den gewünschten Begriff findet.
\R Jeder Zeilenumbruch test\R Reagiert auf Windows \r\n, Linux \n und Mac OS \r

Zeichenklassen

Beinhalten Klassen von Zeichen und sind eine Erweiterung der Suchklassen, welche zwar gut für die Positionierung im String, doch nicht vielfältig genug für internationale Suchstrings sind.

Muster Bedeutung Beispiel Bemerkungen
[:alnum:] Buchstaben und Zahlen 5 oder A -
[:alpha:] Buchstaben x oder Q -
[:ascii:] ASCII-Zeichen - Codes von 0 - 127
[:blank:] Leerzeichen " " Matcht nur für Tab und Leerzeichen
[:cntrl:] Steuerzeichen - -digit
[:digit:] Zahlen 6 Entspricht \d
[:graph:] Druckzeichen - Druckzeichen ohne Leerzeichen
[:lower:] kleine Buchstaben - der Modifier /i wird in diesem Fall ignoriert
[:print:] Druckzeichen mit Leerzeichen - -
[:punct:] Druckzeichen ohne Buchstaben und Zahlen - -
[:space:] Leerzeichen - Nicht exakt \s
[:upper:] grosse Buchstaben F, L der Modifier /i wird in diesem Fall ignoriert
[:word:] Wörter - entspricht \w
[:xdigit:] Hexadezimale Zeichen 9F -

Modifikatoren

Damit das Suchmuster nicht zu komplex wird, kann man dieses modifizieren. Diese Modifikatoren werden anschliessend ans Suchmuster übergeben:

/Muster/Modifikator

Es werden nciht alle Modifikatoren aufgelistet. Eine vollständige Tabelle findet man auf der PHP-Seite.

Zeichen Bedeutung Beispiel Bemerkungen
/D Zeilenende konsequent auf Stringende setzen /Hallo$/D Bei Multiline-Strings liefert die Funktion nur in der letzten Zeile TRUE. Wird gleichzeitig der Modifikator m gesetzt, so wird D ignoriert.
/i Gross- und Kleinschreibung wird ignoriert /Hallo/i Findet auch hallo oder hALLo
/m "Neue Zeile" Zeichen einbeziehen /^Test/sm Ermöglicht den Einsatz von ^ und $ für jede neue Zeile. In diesem Fall wird Test gefunden, auch wenn es erst auf der zweiten Zeile steht, doch auch dort muss es am Anfang der Zeile sein. Damit dies funktioniert, muss s zwingend mitgegeben werden. Ohne "^", "$" oder "\n" wird "m" ignoriert.
/o Ersetzungen nur einmal vornehmen {...} ?
/s . trifft auch auf \n zu /miau.wuff/s Hier darf das Zeichen auch ein Zeilenumbruch sein (Wichtig für Multiline-Eingaben).
/u utf-8 einbinden /Ächz/u Funktioniert auch dann, wenn der Text als utf8 vorliegt. Wenn die Suche auf ungültige Codes stösst, wird einfach "nicht gefunden" zurückgeliefert, egal ob der Text im Suchstring snthalten war. Siehe auch der Hinweis unten, wie man vorgeht, wenn das UTF-8-Flag nicht gesetzt ist.
/x Leerzeichen ignorieren /miau/x Findet auch m i a u oder mi au

Leerzeichen in der Modifikatorenliste werden von PHP ignoriert. Setzt man hingegen ein nicht definiertes Zeichen, so führt dies zu einem Fehler.

Delimiter

Im Gegensatz zu Posix, muss man in PHP den Suchstring mit speziellen Endzeichen (Delimiter) versehen. Zulässig sind nichtalphanumerische Zeichen und es darf auch nicht der Backslash(\) und auch keine Leerzeichen verwendet werden. Häufig werden folgende Muster eingesetzt:

/foo bar/
#^[^0-9]$#
+php+
%[a-zA-Z0-9_-]%

Man kann auch die Klammern ()[]<>{} verwenden. Da die Endzeichen maskiert werden müssen, wenn man nach ihnen sucht, sollte man diese evtl. ersetzen, wenn sie häufig im Suchtext vorkommen, um die Lesbarkeit zu erhöhen. #http://# liest sich besser als/http:\/\//


Beispiele

// den Hostnamen aus URL holen
preg_match('@^(?:http://)?([^/]+)@i',"http://www.php.net/index.html", $treffer);
$host = $treffer[1];
// die letzten beiden Segmente aus Hostnamen holen
preg_match('/[^.]+\.[^.]+$/', $host, $treffer);
echo "Der Domänen-Name lautet: {$treffer[0]}\n";

Anwendung in PHP

In PHP wird preg-match eingesetzt. Unterschiede zu pearl und zu Posix sind vorhanden, doch sind die Auswirkungen meist nur in Spezialfunktionen ersichtlich. Für Konvertierungen einfach die entsprechenden Punkte durchgehen.
PHP kann auch rekursiv arbeiten mit dem Operator (?R). Ich habe hier kein Beispiel, da es komplex ist. Einfach wenn man etwas analysiert, damit man weiss, was die Zeichenfolge bedeutet.

Fehlerbehandlung

Um den letzten Fehler zu überprüfen, setzt man preg_last_error ein. Dieser kann auf einen Wert grösser 0 geprüft werden. Die entsprechende Fehlermeldung kann über die PHP-PRCE-Konstanten abgefragt werden:
if (preg_last_error() == PREG_BACKTRACK_LIMIT_ERROR) {.

Rückgabewert der Funktion

Der Rückgabewert ist 1, wenn der String im Suchmuster gefunden wurde, 0, wenn er nicht gefunden wurde und FALSE, falls ein Fehler auftrat. Entsprechend muss der Rückgabewert mit === FALSE geprüft werden, um zu vermeiden, dass eine erfolglose Suche als Fehler ausgewertet wird.

Verwendung von UTF8

Falls man UTF-8 Texte einsetzt und das PCRE UTF-8Flag nicht aktiviert ist, muss man folgende Sequenz vor das Suchmuster stellen: (*UTF8)

#(*UTF8)alnum:# findet 'ü', während '#alnum:#' nichts findet

For example we would like to search for Japanese-standard circled numbers 1-9 (Unicode codes are 0x2460-0x2468) in order to make it through the hex-codes the following call should be used:

preg_match('/[\x{2460}-\x{2468}]/u', $str);

Here $str is a haystack string
\x{hex} - is an UTF-8 hex char-code
and /u is used for identifying the class as a class of Unicode chars.

Für detaillierte Angaben gibt es die UTF8-Seite.

dynamische Suchfunktion maskieren

Damit dynamische Strings korrekt verwendet werden, wird preg-quote eingesetzt. Wichtig zu beachten ist, dass der Slash(/) nicht automatisch ersetzt wird. Hier muss man den Delimiter explizit angeben:

$schluesselwoerter = '$40 für einen G3/400';
$schluesselwoerter = preg_quote($schluesselwoerter, '/');

Suchen und ersetzen

Hierzu preg_replace einsetzen.

Zeichenkette aufteilen

Hier kann man preg_split verwenden.

Alternativen

Verwenden Sie nicht preg_match(), wenn Sie nur überprüfen wollen, ob eine Zeichenkette in einer anderen Zeichenkette enthalten ist. Verwenden Sie dafür stattdessen die Funktion strpos(), die das schneller erledigt.