Fortgeschrittene - Freitag, Februar 22, 2008 16:20

Reguläre Ausdrücke

„Oft gehört – nie verstanden“ fällt vielen PHP - Programmierern spontan ein, wenn Sie Reguläre Ausdrücke (oder engl. Regular Expressions - RegExp) hören. Dieser Artikel behandelt die Verwendungsmöglichkeiten und den Syntax Regulärer Ausdrücke in Zusammenhang mit PHP.

Zunächst einmal sollte geklärt werden worum es sich überhaupt handelt: Reguläre Ausdrücke sind bestimmte Suchmuster nach denen ein String durchsucht werden kann. Eingesetzt werden Reguläre Ausdrücke beispielsweise zum Durchsuchen (und Ersetzen) oder zur Überprüfung eines Strings.

Um langsam auf den RegExps Syntax hinzuführen, bedienen wir uns zunächst eines einfachen Beispiels:

Wir suchen in einem String nach „php.net“:

<?php
$string 
“Das PHP Manual findet man unter php.net.”
$regexp “/php\.net/i”
if(
preg_match($regexp$string)) { 
    echo 
“Der String ”<b>“.$string.”</b>“ beinhaltet den Begriff php.net”

?>

In diesem Fall wird die Funktion PHP-Funktion preg_match() verwendet. Es lassen sich aber noch viele weitere PHP-Funktionen in Verbindung mit RegExps verwenden:
php.net/manual/de/ref.regex.php

Jetzt möchten wir einen genaueren Blick auf den verwendeten Regulären Ausdruck, also dem Inhalt der Variablen $regexp, werfen.
Jeder regulärer Ausdruck beginnt zunächst mit einem Slash „/“.

Daraufhin können normale Zeichen (nicht alphanumerische Zeichen müssen per „\“ „escaped“ werden) oder Metazeichen folgen. Die Metazeichen sind das Herzstück eines Regulären Ausdruck und dienen zur Beschreibung des Ausdrucks. Falls man ein Metazeichen innerhalb der RegExp in seiner eigentlich Form benötigt, so muss man dieses „escapen“.

Die Metazeichen im Überblick:
\ Zum „escapen“ von nicht alphanumerischen Ausdrücken
^ Kennzeichnet den Anfang eines Suchmusters
$ kennzeichnet das Ende eines Suchmusters
. steht für jedes beliebiges Zeichen
( bzw. ) Unterausdrücke/Teilmuster innerhalb eines RegExp
[ bzw. ] umschließen einer Zeichenklasse, d.h. alle Zeichen einer bestimmten Art
{ bzw. } zur Angabe der Häufigkeit von Zeichen
| für die Unterscheidung zwischen mehreren Möglichkeiten (oder)
? für genau ein oder kein Zeichen
+ für genau ein oder mehrere Zeichen
* für kein Zeichen oder für eine Anzahl beliebig vieler Zeichen

Am Ende jeder RegExp findet man einen Slash „/“ (= Ending Delimiter) und eventuell einen Buchstaben. Dieser Buchstabe ist der sogenannte PCRE-Modifier.
Die gängigsten PCRE-Modifiers: (Auszug)
A - Startet die Suche immer am Anfang eines Strings
e - findet nur bei der Funktion preg_replace Verwendung: der Ersatzstring wird wie PHP Code behandelt.
i - Hier wird Groß- und Kleinschreibung ignoriert.
m - Die Suche erfolgt über mehrere Zeilen
s - Auch Zeilenumbrüche gelten als „jedes beliebige Zeichen“
u - UTF-8 Encoding des Suchmusters
U - Unterdrückt die “Greediness” (Gier) des Regulären Ausdrucks, d.h. es wird dann nicht versucht soviele Übereinstimmungen wie möglich zu finden.
x - Alle nicht sichtbaren Zeichen im Suchmuster werden ignoriert und es ist möglich innerhalb der RegExp per # zu kommentieren.

Soweit die Theorie, folgende Beispiele mögen das o.g. noch einmal veranschaulichen:

/([A-Za-zÄäÖöÜüß]+)/

Sucht nach allen Wörtern mit mindestens einem Buchstaben (daher das Metazeichen „+“), die nur aus den im deutschen Alphabet vorkommenden Zeichen bestehen.

/([^A-Za-zÄäÖöÜüß0-9]+)/

Mit dieser Funktion wird eine Eingabe dahingehend überprüft, dass nur Alphanumerische Zeichen enthalten sind. Das Metazeichen „^“ kehrt die Zeichenklasse um. Alternativ könnte man hier auch [:alnum:] zur Bestimmung der Zeichenklasse verwenden. Mit dieser Funktion kann z.B. verhindert werden, dass ein Formularfeld, das in einer Datenbankabfrage verwendet Zeichen wir „;“ oder „’“, etc. enthält, die ein Sicherheitsrisiko darstellen könnten.

“^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,4})$”
[i]

Diese Regular Expression wird zum Überprüfen eine E-Mail Adresse auf ihre Richtigkeit verwendet. Alle E-Mail Adressen sind ja bekanntlich nach einem bestimmten Schema aufgebaut:
[Buchstaben,Zahlen,_,-,.] @ [buchstaben,Zahlen,-,.] . [2-4 Buchstaben]

Dieser Tatsache bedient sich der obige Ausdruck, den wir jetzt in die Einzelteile zerlegen, um ihn verständlicher zu machen.

Mit ^ beginnt ein Suchmuster.

[i][_a-z0-9-]+

Die erste Zeichenklasse wird durch die eckigen Klammern definiert. In dieser Zeichenklasse dürfen neben Unter- und Bindestrichen sämtliche Buchstaben des Alphabets sowie Zahlen vorkommen. Das „+“ Zeichen drückt aus, dass mindestens ein Zeichen vorhanden sein muss. Diesem Block folgt die gleiche Zeichenklasse ein weiteres mal, nur ist diesmal am Anfang ein . (Punkt) erlaubt, gefolgt von einer Anzahl beliebig vieler Zeichen:

+(\.[_a-z0-9-]+)*

Der Punkt und die Zeichenkette hinter diesem Punkt sind optional, daher das Metazeichen * (Kein oder beliebig viele Zeichen).

Somit ist das Teilstück der E-Mail Adresse vor dem @ verifiziert:

Kombinationen wie name@ vorname.name@ und vorname1.name2@ name123@ etc. sind also erlaubt. Nicht erlaubt wären z.B. Sonderzeichen außer Punkt, Unter- und Bindestrich, sowie keine Angabe.

Als nächster Bestandteil der Reqexp kommt das @, das genau „so wie es ist“ vorkommen muss, daher erübrigt es sich mit Zeichenklassen, etc zu arbeiten.

Als nächstes folgt bekanntermaßen der Domainname. Ein Domainname besteht aus allen alphanumerischen Zeichen,
[a-z0-9-]+
eventuell getrennt durch Punkte (Subdomains),
(\.[a-z0-9-]+)*
und dem Länderkürzel (2-4 Buchstaben) am Ende
*(\.[a-z]{2,4})
Das $-Zeichen beschreibt schließlich das Ende des Suchmusters.

So aufgeschlüsselt ist dieser Reguläre Ausdruck recht einfach zu verstehen. Anwendung in PHP findet er meist mit den Funktionen ereg() und eregi(), die dann true oder false zurückgeben: php.net/ereg.

Ein weitere interessanter Aspekt ist das sog. „Referencing“. Mit einem Backslash gefolgt von einer Zahl lässt sich so auf ein vorangegangenes Suchmuster referenzieren. Die Zahl steht jeweils für die Position des Suchmusters innerhalb des Regulären Ausdrucks. Dies findet man besonders häufig im Zusammenhang mit „Suchen und Ersetzen“ Funktionen (preg_replace). Dabei muss beachtet werden, dass, falls aus dem Ersatz-String auf den Regulären Ausdruck referenziert wird der Backslash noch einmal „escaped“ werden muss.

Anhand einiger Beispiele lässt sich diese Thematik erläutern:

Möchte man z.B. den sogenannten BB-Code in einem String ersetzen so kann man per

preg_replace(“/\[i\](.*)\[\/i\]/isU”,”\\1”,$str);

den BB-Tag „kursiv“ zu HTML transformieren.

Es gibt jedoch auch Verwendungsmöglichkeiten für das „Back-Referencing“ außerhalb der Suchen-Ersetzen Funktionen:

In einem normalen deutschen Text ist es recht ungewöhnlich, dass zwei gleiche Wörter direkt aufeinander folgen. Mit einem regulären Ausdruck und der PHP Funktion preg_match_all kann man einen String auf das wiederholte Vorkommen gleicher Zeichenketten überprüfen. Dazu benötigt man außerdem noch das bisher noch nicht erwähnte nicht-Wortzeichen „\W“ sowie die Beschränkung des Suchmusters auf nur ein Wort per „\b“.

/([A-Za-zÄäÖöÜüß]+\W+\1\b/

Mit \1 wird hier auf das vorhergegangene, also das 1. Suchmuster des Ausdrucks, zurück-referenziert.



Kommentieren

wichtige Artikel