PHP/Reguläre Ausdrücke: Unterschied zwischen den Versionen
Michi (Diskussion | Beiträge) |
Michi (Diskussion | Beiträge) |
||
Zeile 121: | Zeile 121: | ||
| <tt><nowiki>"^(Dr|Prof)\."</nowiki></tt> || Dr.<br>Prof. || Erkennung von Zeichenketten, die mit der Folge von "Dr." oder "Prof." beginnen. Der sonst als Sonderzeichen behandelte Punkt wird hier mit dem Backslash entwertet und zum normalen Zeichen gemacht. | | <tt><nowiki>"^(Dr|Prof)\."</nowiki></tt> || Dr.<br>Prof. || Erkennung von Zeichenketten, die mit der Folge von "Dr." oder "Prof." beginnen. Der sonst als Sonderzeichen behandelte Punkt wird hier mit dem Backslash entwertet und zum normalen Zeichen gemacht. | ||
|- | |- | ||
| <tt><nowiki>"(1|2|3)*0</nowiki></tt> || 1230<br>10<br>2220<br>3210 usw. || Erkennung aller Zeichenfolgen, die mit einer beliebigen Anzahl der Zeichen "1", "2" oder "3" beginnen und mit einer "0" enden. | | <tt><nowiki>"(1|2|3)*0"</nowiki></tt> || 1230<br>10<br>2220<br>3210 usw. || Erkennung aller Zeichenfolgen, die mit einer beliebigen Anzahl der Zeichen "1", "2" oder "3" beginnen und mit einer "0" enden. | ||
|- | |- | ||
| <tt>"^.{5}"</tt> || Sechs<br>Hausboot usw. || Erkennung einer Folge von fünf beliebigen Zeichen am Anfang einer Zeichenkette. | | <tt>"^.{5}"</tt> || Sechs<br>Hausboot usw. || Erkennung einer Folge von fünf beliebigen Zeichen am Anfang einer Zeichenkette. | ||
|- | |- | ||
| <tt>".[0-9]</tt> || A0<br>23<br>x7<br>R9 usw. || Erkennung eines beliebigen Zeichens, gefolgt von einer beliebigen Ziffer (zwischen "0" und "9"). | | <tt>".[0-9]"</tt> || A0<br>23<br>x7<br>R9 usw. || Erkennung eines beliebigen Zeichens, gefolgt von einer beliebigen Ziffer (zwischen "0" und "9"). | ||
|- | |- | ||
| <tt><nowiki>"([a-z]|[A-Z])[0-9]"</nowiki><br><nowiki>"([a-zA-Z])[0-9]"</nowiki></tt> || A0<br>x7<br>R9 usw. || Erkennung eines beliebigen Buchstabens (zwischen "a" und "z" bzw. "A" und "Z"), gefolgt von einer beliebigen Ziffer (zwischen "0" und "9"). | | <tt><nowiki>"([a-z]|[A-Z])[0-9]"</nowiki><br><nowiki>"([a-zA-Z])[0-9]"</nowiki></tt> || A0<br>x7<br>R9 usw. || Erkennung eines beliebigen Buchstabens (zwischen "a" und "z" bzw. "A" und "Z"), gefolgt von einer beliebigen Ziffer (zwischen "0" und "9"). | ||
Zeile 135: | Zeile 135: | ||
| <tt>"[0-9]%"</tt> || 17%<br>6%% || Erkennung von Zeichenfolgen, in denen eine beliebige Ziffer vor einem Prozentzeichen steht. | | <tt>"[0-9]%"</tt> || 17%<br>6%% || Erkennung von Zeichenfolgen, in denen eine beliebige Ziffer vor einem Prozentzeichen steht. | ||
|- | |- | ||
| <tt>"[0-9],[0-9]</tt> || 3,4<br>A3,89 usw. || Erkennung von Zeichenfolgen, in denen eine beliebige Ziffer vor einem Komma steht, gefolgt von einer beliebigen Ziffer. | | <tt>"[0-9],[0-9]"</tt> || 3,4<br>A3,89 usw. || Erkennung von Zeichenfolgen, in denen eine beliebige Ziffer vor einem Komma steht, gefolgt von einer beliebigen Ziffer. | ||
|- | |- | ||
| <tt>"[^a-zA-Z]"</tt> || || Ausschluss aller Buchstaben. | | <tt>"[^a-zA-Z]"</tt> || || Ausschluss aller Buchstaben. |
Version vom 20. Februar 2009, 13:58 Uhr
Reguläre Ausdrücke
In einem regulären Ausdruck (engl. regular expression) steckt bei genauer Betrachtung ein vollständiges Programm. Intern arbeitet nicht einfacher Mustervergleich, sondern die Regex-Maschine - ein Programm, das die Ausdrücke auflöst und ausführt. Die Ausführung einer umfangreichen Suche mit einem regulären Ausdruck kann spürbar viel Rechenzeit beanspruchen; es ist durchaus möglich, dass solche Gebilde zu Programmschleifen führen, Abstürze verursachen und sich auch sonst wie andere Programme daneben benehmen. Komplexe Aussagen lassen sich oft auf mehr als einem Weg ausdrücken - der erste Weg ist vielleicht schneller, der zweite kompakter, der dritte verständlicher.
Reguläre Ausdrücke beschreiben Suchmuster, die so komplex sein können, dass sich ganze Filter in einer Zeile beschreiben lassen. Durch Schalter und Funktionen werden diese Muster dann zu einem mächtigen Werkzeug. Die einfachste Form, ein Suchmuster anzugeben, besteht in der Klammerung einer Zeichenkette mit Anführungszeichen.
"Suchmuster"
Die Steuerung innerhalb des Suchmusters wird durch besondere Schalter vorgenommen, mit deren Hilfe die Suchfunktionen erkennen kann, wo die zu suchende oder zu ersetzende Zeichenkette beginnt und wo sie endet.
Schalter | Bedeutung |
---|---|
^ | Kennzeichnet den Beginn einer Zeichenkette. Innerhalb eckiger Klammern ("[^]") negiert dieses zeichen die Auswahl. |
$ | Kennzeichnet das Ende einer Zeichenkette. |
* | Keines oder beliebig viele Zeichen. Entspricht "{0,}". |
+ | Ein oder mehr Zeichen. Entspricht "{1,}". |
? | Keines oder genau ein Zeichen. Entspricht "{0,1}". |
{} {,} |
Feinere Steuerung der Wiederholung. Bei Verwendung des Kommas, setzt der zweite Parameter die obere Grenze. |
() | Gruppierung. |
(|) | Gruppierung mit oder-Operator. |
. | Der Punkt entspricht genau einem beliebigen Zeichen. |
[] | Auswahl aus einer Gruppe von Zeichen. Die Zeichen in den eckigen Klammern stehen immer für genau ein Zeichen. Innerhalb der eckigen Klammern verlieren die Sonderzeichen ihre Bedeutung, es wird dann also immer nach dem zeichen selbst gesucht. |
[^] | Auswahl aus einer Gruppe von Zeichen, die nicht vorkommen dürfen. Die Zeichen in den eckigen Klammern stehen immer für genau ein Zeichen. |
Alle diese Sonderzeichen können natürlich auch in normalen Zeichenketten auftreten. Um dort in ihrer normalen Bedeutung nach ihnen zu suchen, müssen sie mit dem Backslash ("\") gekennzeichnet werden. Der Backslash selbst etwa wird also als "\\" geschrieben. Hier eine Zusammenfassung aller Sonderzeichen.
^ . [ ] $ ( ) | * + ? { } \
Reguläre Ausdrücke in PHP arbeiten nach dem POSIX-Standard 1003.2, der auch die Angabe generischer Zeichenklassen innerhalb der KLassendefinition "[]" erlaubt.
POSIX- Ersatzsymbol |
Bedeutung |
---|---|
[:alnum:] | Alphanumerische Zeichen. "alnum:" entspricht "[a-zA-Z0-9]". |
[:alpha:] | Zeichen des Alphabets. |
[:digit:] | Numerische Zeichen (Ziffern, Plus, Minus). |
[:blank:] | Leerzeichen und Tabulator. |
[:space:] | Alle "weissen" Zeichen. |
[:punct:] | Satzzeichen. |
[:lower:] | Kleinbuchstaben. |
[:upper:] | Grossbuchstaben. |
[:cntrl:] | Steuerzeichen. |
[:graph:] | Druckbare und sichtbare Zeichen. |
[:print:] | Alphanumerische Zeichen. |
[:xdigit:] | Hexadezimale Zeichen (0-9, a-f, A-F). |
Neben dem Suchen dienen reguläre Ausdrücke oft auch zum Ersetzen von Teilen von Zeichenketten. Auch bei der Angabe der Ersatzzeichen sind einige Sonderzeichen möglich.
Sonderzeichen | Bedeutung |
---|---|
\n | Zeilenumbruch (engl. newline). |
\t | Tabulator. |
Einfache Beispiele
Einige Beispiele veranschaulichen die Nutzung dieser Schalter.
Beispiel | Entsprechung | Beschreibung |
---|---|---|
"^Skript" | Skript Skripts Skriptsprache Skriptprogrammierer usw. nicht: PHP-Skript |
Erkennung aller Zeichenketten, die mit den Zeichen "Skript" beginnen. |
"sprache$" | Skriptsprache Programmiersprache usw. nicht: Die Sprachschule nicht: Sprachenschatz |
Erkennung aller Zeichenketten, die auf die Zeichen "sprache" enden. |
"^PHP$" | PHP | Erkennung aller Zeichenketten, die genau dem Suchmuster entsprechen. |
"ript" | Skript Skriptsparche script Skriptprogrammierer usw. |
Erkennung der Zeichen "ript" an einer beliebigen Stelle im Suchwort. |
"12*" | 1 12 122 1222 usw. |
Erkennung von Zeichenketten, die eine "1" und daran anschliessend eine beliebige Anzahl (also auch keine) "2" enthalten. |
"12+" | 12 122 1222 usw. |
Erkennung von Zeichenketten, die eine "1" und daran anschliessend mindestens eine "2" enthalten. |
"12?" | 1 12 |
Erkennung von Zeichenketten, die eine "1" und daran anschliessend keine oder eine "2" enthalten. |
"1?2+$" | 12 2 122 2222 usw. |
Erkennung aller Zeichenketten, die keine oder eine "1" enthalten, gefolgt von mindestens einer "2", wobei alle diese Zeichen jeweils am Ende der Zeichenkette stehen müssen. |
"DL{2}" | DLL | Entspricht einer Zeichenfolge von "D", gefolgt von genau zwei aufeinanderfolgenden "L". |
"DL{2,}" | DLL DLLL DLLLL usw. |
Entspricht einer Zeichenfolge von "D", gefolgt von mindestens zwei aufeinanderfolgenden "L". |
"DL{2,3}" | DLL DLLL |
Entspricht einer Zeichenfolge von "D", gefolgt von genau zwei oder drei aufeinanderfolgenden "L". Ein gültiger Ausdrück wäre auch "DL{0,3}" - nicht gültig wäre jedoch "DL{,3}". |
"{0,}" | * | |
"{1,}" | + | |
"{0,1}" | ? | |
"1(34)*" | 1 134 13434 usw. |
Erkennung von Zeichenketten, die eine "1" und eine beliebige Folge von "34" enthalten. |
"1(34){1,2} | 134 13434 |
Erkennung von Zeichenketten, die eine "1" und einmal oder zweimal die Folge von "34" enthalten. |
"(Dr|Prof)" | Dreher Professur usw. |
Erkennung von Zeichenketten, die an beliebiger Stelle die Folge von "Dr" oder "Prof" enthalten. |
"^(Dr|Prof)\." | Dr. Prof. |
Erkennung von Zeichenketten, die mit der Folge von "Dr." oder "Prof." beginnen. Der sonst als Sonderzeichen behandelte Punkt wird hier mit dem Backslash entwertet und zum normalen Zeichen gemacht. |
"(1|2|3)*0" | 1230 10 2220 3210 usw. |
Erkennung aller Zeichenfolgen, die mit einer beliebigen Anzahl der Zeichen "1", "2" oder "3" beginnen und mit einer "0" enden. |
"^.{5}" | Sechs Hausboot usw. |
Erkennung einer Folge von fünf beliebigen Zeichen am Anfang einer Zeichenkette. |
".[0-9]" | A0 23 x7 R9 usw. |
Erkennung eines beliebigen Zeichens, gefolgt von einer beliebigen Ziffer (zwischen "0" und "9"). |
"([a-z]|[A-Z])[0-9]" "([a-zA-Z])[0-9]" |
A0 x7 R9 usw. |
Erkennung eines beliebigen Buchstabens (zwischen "a" und "z" bzw. "A" und "Z"), gefolgt von einer beliebigen Ziffer (zwischen "0" und "9"). |
"[a-f0-9]" | a0 c7 usw. |
Erkennung eines Buchstabens in Kleinschreibung, gefolgt von einer beliebigen Ziffer. Eignet sich z. B. zur Erkennung hexadezimaler Zahlen. |
"^[a-zA-Z]" | Anton sauer usw. |
Erkennung von Zeichenfolgen, die mit einem Buchstaben beginnen. |
"[0-9]%" | 17% 6%% |
Erkennung von Zeichenfolgen, in denen eine beliebige Ziffer vor einem Prozentzeichen steht. |
"[0-9],[0-9]" | 3,4 A3,89 usw. |
Erkennung von Zeichenfolgen, in denen eine beliebige Ziffer vor einem Komma steht, gefolgt von einer beliebigen Ziffer. |
"[^a-zA-Z]" | Ausschluss aller Buchstaben. | |
"[?+\|]" | Erkennt ein beliebiges der Zeichen "?", "+", "\" und "|". |
Komplexere Beispiele
Eingabefelder in HTML-Formularen akzeptieren nur Zeichenketten. Es obliegt dem Entwickler, die eingetragenen Werte auf richtige Schreibweise hin zu untersuchen. Reguläre Ausdrücke können das in einer einzigen Programmzeile erledigen.
Werden etwa Geldwerte erwartet, so können diese unterschiedlich eingegeben werden; 1522 Franken können auch "1522", "1'522", "1522.00" oder "1'522.00" sein. Die Entwicklung des passenden regulären Ausdrucks wird im folgenden schrittweise vorgestellt. |
Folgender Ausdruck akzeptiert nur Ziffern und Ziffernfolgen. Das erste Zeichen darf nicht 0 sein. ^[1-9][0-9]*$ Folgender Ausdruck akzeptiert nur Ziffern und Ziffernfolgen. Das erste Zeichen darf nicht 0 sein, eine einzelne 0 wird aber akzeptiert. ^(0|[1-9][0-9]*)$ Folgender Ausdruck akzeptiert nur Ziffern und Ziffernfolgen. Das erste Zeichen darf nicht 0 sein, eine einzelne 0 wird aber akzeptiert. Zusätzlich wird ein Minuszeichen erlaubt, wenn der Wert nicht 0 ist. ^(0|-?[1-9][0-9]*)$ Folgender Ausdruck akzeptiert mehrere Ziffern vor und nach dem Punkt. ^[0-9]+(\.[0-9]+)$ Folgender Ausdruck akzeptiert mehrere Ziffern vor und genau zwei Ziffern vor und nach dem Punkt. ^[0-9]+(\.[0-9]{2})$ Folgender Ausdruck akzeptiert mehrere Ziffern vor und eine oder zwei Ziffern nach dem Punkt. Der Ausdruck akzeptiert Zahlen ohne und mit Punkt, dafür sorgt das Fragezeichen nach der Klammer (ein- oder keinmal). ^[0-9]+(\.[0-9]{1,2})?$ Folgender Ausdruck akzeptiert mehrere Ziffern vor und eine oder zwei Ziffern nach dem Punkt. Der Ausdruck akzeptiert Zahlen ohne und mit Punkt, dafür sorgt das Fragezeichen nach der Klammer (ein- oder keinmal). Zusätzlich wird das Tausendertrennzeichen "'" akzeptiert. Zahlen wie "1'555" werden ebenso akzeptiert wie "34.55". ^[0-9]{1,3}(\.[0-9]{3})*(\.[0-9]{1,2})?$ Folgender Ausdruck akzeptiert eine einzelne Null, ebenso aber mehrere Ziffern vor und eine oder zwei Ziffern nach dem Punkt. Der Ausdruck akzeptiert Zahlen ohne und mit Punkt, dafür sorgt das Fragezeichen nach der Klammer (ein- oder keinmal). Zusätzlich wird das Tausendertrennzeichen "'" akzeptiert. Zahlen wie "1'555" werden ebenso akzeptiert wie "34.55". ^[0-9]+|[0-9]{1,3}(\.[0-9]{3})*(\.[0-9]{1,2})?$ |
Bei der weiteren Auswertung ist zu beachten, dass die Untersuchung einer Zeichenkette mit Hilfe regulärer Ausdrücke noch keine Bewertung darstellt.
Bevor eine Zeichenkette für mathematische Operationen nutzbar wird, müssen die Tausendertrennzeichen entfernt werden. Falls als Dezimaltrennzeichen (wie in Deutschland) das Komma eingesetzt wird, muss es durch einen Punkt ersetzt werden, da PHP intern mit US-amerikanischen Zahlenformaten rechnet.
Die E-Mail-Adresse taucht häufig in Eingaben auf. Hier ist es möglich, mit Hilfe von Anfragen an Nameserver das Vorhandensein einer Domain zu testen und andere Massnahmen zu ergreifen, um richtige von falschen E-Mail-Adressen zu unterscheiden. Ein POP3-Mailname kann aus Gross- oder Kleinbuchstaben (die keine Rolle spielen) sowie aus Minuszeichen, Unterstrichen und Punkten bestehen. Nach dem Namen folgt das "@"-Zeichen und der Domainname. Hier dürfen keine Unterstriche auftreten, sonst entspricht sie dem E-Mail-Namen. |
Der E-Mail-Name wird auf gültige Zeichen untersucht. Der Punkt fehlt noch. ^[_a-zA-Z0-9-]+$ Der E-Mail-Name wird auf gültige Zeichen untersucht, wobei auch der Punkt akzeptiert wird - allerdings nicht am Anfang oder Ende des Namens. ^[_a-zA-Z0-9-]+(\.[_a-zA-Z0-9-]+)*$ Hier wird nur der Domainname untersucht. Unterstriche sind nicht erlaubt, der Punkt ist zwingend und wird von zwei bis vier Zeichen gefolgt, die wiederum nur Buchstaben sein können. ^[a-zA-Z0-9-]+\.([a-zA-Z]{2,4})$ Eine Kombination aus dem vorderen und hinteren Teil einer E-Mail-Adresse, verbunden durch das "@"-Zeichen. ^[_a-zA-Z0-9-]+(\.[_a-zA-Z0-9-]+)*@[a-zA-Z0-9-]+\.([a-zA-Z]{2,4})$ Eine Kombination aus dem vorderen und hinteren Teil einer E-Mail-Adresse, verbunden durch das "@"-Zeichen. Zusätzlich ist nun auch die Angabe mehrfacher Domainnamen (z. B. "mailadresse@mail.subdomain.domain.xx" möglich. Dabei darf der erste Teil des zweiten Ausdrucks mehrfach vorkommen, muss aber mindestens einmal erscheinen. ^[_a-zA-Z0-9-]+\.([_a-zA-Z0-9-]+)*@([a-zA-Z0-9-]\.)+([a-zA-Z]{2,4})$ Dasselbe Beispiel könnte auch in folgender Schreibweise dargestellt werden. ^ [_a-zA-Z0-9-]+ (\. [_a-zA-Z0-9-]+ )* @ ( [a-zA-Z0-9-] \. )+ ( [a-zA-Z]{2,4} ) $ |
Funktionen
Funktion | Beschreibung |
---|---|
preg_match | Suche nach einem (dem ersten) Vorkommen des Musters. |
preg_match_all | Suche nach allen Vorkommen des Musters. |
preg_replace | Suchen und Ersetzen aller Vorkommen. |
preg_replace_callback | Suchen und Ersetzen mit Hilfe einer eigenen Funktion, die für jede Fundstelle aufgerufen wird. |
preg_split | Zerlegen einer Zeichenkette in ein Array anhand eines Suchmusters. |
preg_grep | Durchsuchen aller Elemente eines Arrays mit einem regulären Ausdruck. Es werden die Elemente als neues Array zurückgegeben, bei denen die Suchbedingung erfüllt war. |
preg_quote | Markiert Sonderzeichen so, dass sie in regulären Ausdrücken verwendet werden können. |
Die mit PHP 3 eingeführten Funktionen "ereg", "ereg_replace" sollten nicht mehr verwendet werden.
Die Funktionen verlangen den Einbau des Suchmusters in zwei Begrenzungszeichen. Das kann jedes Zeichen sein - jedoch keine Buchstaben, Zahlen oder bereits im regulären Ausdruck selbst vorkommende Zeichen.
Bei der Suche nach Übereinstimmungen können mehrere Treffer zurückgegeben werden. In den folgenden Beispielen wird als Argument deshalb ein Array übergeben, in dem dann mehrere Ergebnisse liegen können.
Die Funktion "preg_match" untersucht eine Zeichenkette anhand eines regulären Ausdrucks und füllt ein übergebenes Array mit Fundstellen. Falls die Suche erfolgreich war, wird "TRUE" zurückgegeben. Im folgenden Beispiel wird die Umwandlung des US-amerikanischen Datumsformats in das deutsche gezeigt.
<?php
$date = "2008-09-16";
echo "<p>Datum zu prüfen: $date</p>\n";
## Plazierung der drei Werte in das Array wird durch Klammerung der
## Ausdrucksteile erreicht.
$preg = "([0-9]{4})-([0-9]{1,2})-([0-9]{1,2})";
if (preg_match( "/$preg/", $date, $regs ) ) {
echo "$regs[3].$regs[2].$regs[1]";
}
else
{
echo "Falsches Datumsformat: $date";
}
?>
|
Datum zu prüfen: 2008-09-16 16.09.2008 |
Die Funktionen können durch Schalter ergänzt werden, die das Verhalten verändern. Die Schalter stehen nach dem letzten Begrenzungszeichen. Interessant ist etwa "i" - damit wird die Unterscheidung von Gross- und Kleinschreibung ausgeschaltet.
"/muster/i"
Mit der Funktion "preg_replace" können die gefundenen Zeichenketten durch andere Zeichenketten ersetzt werden. Im folgenden Beispiel wird die neue (ersetzte) Zeichenkette zurückgegeben. Ergab der reguläre Ausdruck keine Übereinstimmung, so wird die originale Zeichenkette übergeben. "pre_replace" entspricht dem, nur wird die Gross- und Kleinschreibung allgemein nicht beachtet. Die Umwandlung wird auch für Umlaute richtig durchgeführt.
<?php
$email = "test#domain.xx";
echo preg_replace("/#/", "@", $email);
?>
|
test@domain.xx |
Das vorige Beispiel legt die Nutzung der Textersetzungsfunktion "strstr" nahe. Zudem sind Funktionen mit regulären Ausdrücken verhältnismässig langsam. Tatsächlich ist die Anwendung regulärer Ausdrücke zum Ersetzen aber noch weitaus komplexer als bisher beschrieben.
Die Funktion "preg_split" teilt eine Zeichenkette in Segmente und legt jedes Segment als Element in einem Array ab. Als Suchwort wird dabei ein regulärer Ausdruck akzeptiert. Wird keine Übereinstimmung gefunden, so steht die gesamte Zeichenkette danach im Array im Index 0.
<?php
$email = "name@domain.xx";
$test = preg_split("/@/",$email);
echo "Name: $test[0]<br />\n";
echo "Domain: $test[1]<br />\n";
?>
|
Name: name |