Werbung einblenden Werbung ausblenden


Home / Tutorials / PHP Handbuch / regular expression mit PHP


regular expression mit PHP
Die Funktion preg_match
Die Funktion preg_match_all
Feststellen, ob eine Zeichenkette nur aus Zahlen besteht
Gierige und nicht nicht gierige Erweiterungen
Eine Wortgrenze festlegen
Eine Gruppe negieren
Unterscheidung zwischen Groß- und Kleinschreibung ausschalten
Mit regular expressions einen Array durchsuchen
Zeichenketten an einer Regular expression trennen
Bestimmte Werte durch eine regular expression ersetzen
Die Funktion preg_replace
Mehrere Teilstrings durch mehrere regular expressions ersetzen

regular expression mit PHP

Regular expressions sind die abstrakte Formulierung eines wie auch immer strukturierten Textes. Email Adressen haben eine Struktur, die Adresse einer Website hat eine Struktur, eine Telefonnummer hat eine Struktur, eine Postleitzahl hat eines Struktur. Alles was eine Struktur hat, lässt sich über regular expressions durchsuchen und verändern. Machen wir uns das an einem konkreten Beispiel klar.
Eine Adresse wie Andres_Ehmann@web.de hat eine Struktur. Zuerst kommt eine Reihe alphanummerischer Zeichen, ein Punkt oder ein Unterstrich, dann ein @ Zeichen, dann wieder eine Reihe alphanummerischer Zeichen Punkt oder Unterstrich, als letztes Element muss ein Punkt kommen dann eine Einheit von mindestens zwei und höchstens drei Buchstaben. Will man also zum Beispiel alle email Adressen in einer Website finden, dann muss man diese Struktur nachbilden. Machen wir und das nochmal klar. Wir haben folgende email-Adressen.

Andres_Ehmann@web.de
infos@infos24.de
ron_sommer@t-online.de
breitschwerdt@mercedes-benz.com

Alle diese Adressen haben folgende Struktur.

[beliebige Anzahl Buchstaben oder Zahlen oder . oder _ oder -]
[@ Zeichen]
[beliebige Anzahl Buchstaben oder Zahlen oder . oder _ oder -]
[.]
[mindestens zwei höchstens vier Buchstaben]

Das oben stehende ist die abstrakte Formulierung einer email-Adresse, wenn auch in Pseudo Code. Man könnte also durch Eingabe einer solch abstrakt formulierten Struktur alle email-Adressen finden. Man könnte aber noch mehr tun. Man könnte alles rausfischen, was nach dem Zeichen "@" kommt, also die Domains, web.de, mercedes-benz.com, t-online oder das was vor dem Zeichen "@" steht ändern in info etc. etc. Regular expressions haben für die Internet Programmierung eine enorme Bedeutung. In Zukunft werden aber auch wohl alle Bibliotheken mit Programmen ausgestattet sein, die mit regular expressions arbeiten. Das würde das finden von Büchern enorm vereinfacht (Zeige mir alle Bücher, wo die Wörter Gold, siglo de oro, Südamerika vorkommen, alle Bücher wo Helmut Kohl und Gorbatschev vorkommen etc. etc.) PHP hat alle regular expressions von Perl übernommen teilweise aber auch die Leistungsfähigkeit nochmal erweitert. Die Stärke der regular expressions liegt darin, dass mit Hilfe von regular expressions auch Textstrukturen erkannt werden können, die sehr schwach strukturiert sind. Zusätzlich bietet PHP sehr viel mehr fertige Funktionen zum Bearbeiten von Zeichenketten an, so daß in bestimmten Fällten auf regular expressions sogar verzichtet werden kann siehe Funktionen zum bearbeiten von Zeichenketten. Fangen wir mit dem einfachsten Fall an

Die Funktion preg_match

<?
$string="James Joyce und Virginia Wolf sind die größten englischsprachigen Schriftsteller";
$treffer=preg_match("/Virginia/", $string);
print $treffer;
?>

Das Ergebnis ist eins, weil Virginia in der Variable $string enthalten ist. Der Aufbau der Funktion preg_match ist etwas eigenartig. Der erste Parameter, Virginia, wird sowohl von Slashes (/) als auch von Anführungsstrichen umklammert. Die Anführungsstriche sind hierbei lediglich die Begrenzer des Parameters, die Slashes sind die Begrenzer der regular expression und können weitgehend willkürlich gewählt werden.

<?
$string="James Joyce und Virginia Wolf sind die größten englischsprachigen Schriftsteller";
$treffer=preg_match("!Virginia!", $string);
print $treffer;
?>

Wie deutlich zu sehen, kann auch das Ausrufungszeichen als Begrenzer gewählt werden, oder irgend etwas anderes. Man kann sich aber auch noch für etwas anderes interessieren, nämlich ob ein Wort vorhanden ist vom Typ [mit W starten] [dann zwei Buchstaben] [mit f enden]. In diesem Falle ist es klar, es ist Wolf. Da aber der Mittelteil abstrakt formuliert wurde, will man unter Umständen wissen, was es genau war, es könnte ja auch Wurf oder Werf sein. Man will also das konkrete Wort finden, das mit der abstrakt formulierten Struktur übereinstimmt. In diesem Fall muss man einen dritten Parameter angeben. Dies ist dann der Array, in der der Treffer abgespeichert wird.

<?
$string="James Joyce und Virginia Wolf sind die größten englischsprachigen Schriftsteller";
preg_match("!W..f!", $string,$gefundenes_wort);
print $gefundenes_wort[0];
?>

Wir sehen Wolf auf dem Bildschirm. Dazu gibt es nun ein bisschen was zu sagen. Die regular expression ist W..f. Die Punkte stehen hier für jedes x-beliebige Zeichen, folglich ist die Konstruktion z.B. mit Wolf kompatibel. Es gibt jetzt eine naheliegende Frage. Warum ist der dritte Parameter überhaupt ein Array ? Man hätte es ja genauso gut in eine Skalar Variable packen können. Tatsächlich ist dem nicht so, weil man hier eine Option hat. Man kann sich entweder alles zeigen lassen, was der regular expression entspricht, oder nur einen Ausschnitt aus derselben. Man betrachte folgendes kleines Programm.

<?
$string="James Joyce und Virginia Wolf sind die größten englischsprachigen Schriftsteller";
preg_match("!W(..)f!", $string,$gefundenes_wort);
print "Das ist der Teil, der innerhalb der Klammern steht ". $gefundenes_wort[1]."<br>";
print "Das ist die gesamte regular expression ". $gefundenes_wort[0]."<br>";
?>

Das produziert dann dieses Ergebnis:

Das ist der Teil, der innerhalb der Klammern steht ol
Das ist die gesamte regular expression Wolf

Wir sehen also, dass das zweite Element des Arrays ($gefundenes_wort[1]) nur den Teil erfasst, der innerhalb der runden Klammern steht, also ol für die zwei Punkte, während $gefundenes_wort[0] die gesamte regular expression erfasst. So weit so nett. Was ist aber, wenn die es mehrere Wörter mit der entsprechenden Struktur gibt und wir alle haben wollen. Die Funktion preg_match findet ja nur das erste Wort, dass der Struktur entspricht und bricht dann ab. Um alle Wörter zu finden, brauchen wir die Funktion preg_match_all.

Die Funktion preg_match_all

<?
$string="Maier Mayer Meier Meyer";
preg_match_all("/M(...)r/",$string,$gefundene_woerter);
print "Gesamter Ausdruck, zweiter Treffer ".$gefundene_woerter[0][1]."<br>";
print "Teilausdruck, zweiter Treffer ".$gefundene_woerter[1][1]."<br>";
?>

Das produziert dann dieses Ergebnis:

Gesamter Ausdruck, zweiter Treffer Mayer
Teilausdruck, zweiter Treffer aye

Wir erhalten also zwei zweidimensionale Arrays, einen $gefundene_woerter[0], der die gesamte regular expression für alle gefundenen Wörter beinhaltet (Maier, Mayer, Meier,Meyer) und einen $gefundene_woerter[1], der jeweils den von der runden Klammer umfassten Teil findet (aie,aye,eie,eye). Wenn man will, kann man alle gefundenen Wert ausdrucken.

<?
$string="Maier Mayer Meier Meyer";
preg_match_all("/M(...)r/",$string,$gefundene_woerter);
foreach ($gefundene_woerter[0] as $gesamter_Ausdruck)
{
print "Gesamter Ausdruck: ". $gesamter_Ausdruck."<br>";
}
print "------------------------------------------------------------<br>";
foreach($gefundene_woerter[1] as $gesamter_Ausdruck)
{
print "Gesamter Ausdruck: ".$gesamter_Ausdruck."<br>";
}
?>

Das produziert dann dieses Ergebnis:

Gesamter Ausdruck: Maier
Gesamter Ausdruck: Mayer
Gesamter Ausdruck: Meier
Gesamter Ausdruck: Meyer
------------------------------------------------------------
Gesamter Ausdruck: aie
Gesamter Ausdruck: aye
Gesamter Ausdruck: eie
Gesamter Ausdruck: eye

Durch Angabe eines optionalen vierten Parameters kann man bestimmen, wie die Werte abgespeichert werden. Entweder als zwei zweidimenisonale Arrays, wie oben, oder in mehreren eindimenisonalen Arrays ($gesuchte_woerter[0], $gesuchte_woerter[1],$gesuchte_woerter[2] etc. die dann jeweils zwei Elemente $gesuchte_woerter[0][0]/$gesuchte_woerter[0][1] etc haben. Gibt man nichts an, wie oben, wird PREG_PATTERN_ORDER verwendet. Die Alternative dazu ist PREG_SET_ORDER. Verdeutlichen wir uns die Zusammenhänge nochmal anhand eines Beispiels.

<?
$string="Maier Mayer Meier Meyer";
$treffer=preg_match_all("/M(...)r/",$string,$gefundene_woerter,PREG_SET_ORDER);
for ($i=0;$i<$treffer;$i++)
{
print "Gesamter Ausdruck: ". $gefundene_woerter[$i][0].
" Umklammerter Ausdruck: ".$gefundene_woerter[$i][1]."<br>";
}
?>

Das produziert dann dieses Ergebnis:

Maier aie Mayer aye Meyer eye

Bis jetzt haben wir noch kein ernsthaftes Problem gelöst. Ein ernsthaftes Problem wäre zum Beispiel mit regular expression zu prüfen, ob eine email Adresse, die ein User z.B. über ein HTML Formular eingibt, von ihrer Struktur her korrekt ist. Ein Programm, das so etwas leistet, würde so ähnlich aussehen wie dieser kleine Programm.

<?
$email="Andres_Ehmann@web.de";
$email_flag=preg_match("!^\w[\w|\.|\-]+@\w[\w|\.|\-]+\.[a-zA-Z]{2,4}$!",$email);
print $email_flag;
?>

Nun haben wir eine regular expression in ihrer ganzen Pracht, Blüte und Komplexität. Der Skript setzt 1 auf den Bildschirm, weil die regular expression eine email Adresse tatsächlich konkret beschreibt. Wir erinnern uns an das oben Gesagte. Abstrakt formuliert sieht eine email Adresse so aus.

1) [beliebige Anzahl Buchstaben oder Zahlen oder . oder _ oder -]
2) [@ Zeichen]
3) [beliebige Anzahl Buchstaben oder Zahlen oder . oder _ oder -]
4) [.]
5) [mindestens zwei höchstens vier Buchstaben]

Gehen wir die einzelnen Blöcke durch. Dem 1) Block entspricht

^\w[\w|\.|\-]+@

mit dem Dach (^) teilen wir mit, dass das gesuchte Konstrukt am Anfang der Zeichenkette enthalten sein muss, man muss das weglassen, wenn man z.B. nach email Adressen innerhalb einer HTML Seite sucht. Als nächstes kommt ein Wordelement (\w). Das sind all die Elemente, die unter Unix oder dessen Derivaten Bestandteil eines Dateinamens sein dürfen, also abcdefghijklmnopqrstyxz wie auch ABCDEFGHIJKLMNOPQRSTXYZ wie auch 1234567890 wie auch der Unterstrich _. Kein Wordelement sind äöüß oder Punkt und auch alle anderen Sonderzeichen nicht wie etwa é, spanische Tilde, ceguille etc. Wir gehen also davon aus, dass das erste Element ein Wordelement ist. Nach dem ersten Zeichen kann auch ein Punkt (.) oder Bindestrich erscheinen. A.Ehmann@web.de ist eine gültige emailadresse, genauso wie A-Ehmann@web.de. Folglich müssen wir für das dann folgende Zeichen eine Gruppe bilden. Wir tun das mit der eckigen Klammer [ ]. Mit der eckigen Klammer bilden wir Gruppen. Wir sagen in diesem Fall, dass die folgenden Zeichen entweder ein wordelement \w, ein Punkt \. oder ein Bindestrich \- sein muss. Die Pipe | ist hier das oder Zeichen. Der Punkt muss mit einem Backslash gekennzeichnet werden, weil er ja sonst, siehe oben, für jedes x-beliebige Zeichen stünde. Nach dem Klammerausdruck [\w|\.|\-] haben wir ein + Zeichen. Das heisst, dass die Elemente innerhalb des Klammerausdrucks einmal oder x-beliebig oft vorkommen können. Danach soll ein @ Zeichen kommen. Nach dem @ Zeichen soll, das ist Block 2). Nach dem @ Zeichen, Block 3), kommt wieder die gleiche Gruppe, die oben schon beschrieben wurde [\w|\.|\-]. Anschliessend, Block 4) soll ein Punkt kommen. Danach ein Buchstaben. Ach hier bilden wir wieder eine Gruppe, wählen aber eine Kurzschreibweise. Anstatt abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ schreiben wir [a-zA-Z]. Machen wir uns klar, wie oft ein Element dieses Typs, also ein Buchstabe vorkommen kann. Es handelt sich um die top level domain. Eine solche besteht mindestens aus zwei Buchstaben, de, fr, es, uk kann aber auch drei Buchstaben haben org, net, com, höchstens hat sie aber vier, wie etwa info. Mit der geschweiften Klammer geben wir diese Grenzen an {2,4}. Das heisst, das Element, dass unmittelbar vor der geschweiften Klammer steht muss mindestens 2 und darf höchstens 4 mal auftauchen. Ganz am Schluss setzen wir noch ein Dollarzeichen $. Damit teilen wir mit, dass danach nichts mehr folgen darf. Wir verhindern also, dass eine Adresse der Art Andres_Ehmann@web.aleman als gültig erkannt wird. Ich nehme an, dass an Hand dieses "real world" Beispiels jedem klar geworden ist, wie man mit regular expressions arbeitet. Ich gehe davon aus, dass sich der gesamte Umfang der regular expressions am schnellsten durch Beispiele erschliesst. Beispiel eins:

Feststellen, ob eine Zeichenkette nur aus Zahlen besteht

Anwendungsfall: Man will feststellen, ob eine Zeichenkette tatsächlich aus fünf Zahlen (also einer PLZ) besteht.

<?
$string="13189";
$treffer=preg_match("/^\d{5}$/",$string);
print $treffer;
?>

Die regular expression stimmt mit der Variable $string überein, folglich wird 1 zurückgeben. Mit \d sind alle Zahlen gemeint. Das ist äquivalent zu [0-9]
Beispiel zwei:

Gierige und nicht nicht gierige Erweiterungen

<?
$string="hallo du Mayer, Meyer, Meier";
preg_match("/.*(M..er)/",$string,$wort_in_runden_Klammern);
print $wort_in_runden_Klammern[1];
?>

Wir erinnern uns: Man kann in dem optionalen dritten Parameter den gefundenen Ausdruck speichern. Dabei ist das erste Element des Arrays $wort_in_runden_Klammern der Wert, der der gesamten regular Expression entspricht, das zweite Element der Wert, der dem in runden Klammern stehenden Teil der regular Expression entspricht. Die Frage ist nun, steht da Mayer, Müller oder Meier ? Verblüffender Weise ist das Ergebnis Meier und nicht wie viele erwarten Mayer. Das liegt daran, dass sowohl das Pluszeichen + (das vor dem + Zeichen stehende Zeichen muss mindestens einmal oder beliebig oft auftauchen), wie auch das Sternchen * ( das vor dem * Zeichen stehende Zeichen kann null Mal oder beliebig oft auftauchen) greedy sind, also gierig. Sie greifen durch, bis die Gruppe (in unserem Falle (M..er)) zum ersten Mal auftaucht, sondern bis dahin, wo sie zum letzten Mal auftaucht, also bis Meier. Mayer und Müller werden also übersprungen. Für viele Anwendungen aus der Praxis will man das so. Bei anderen aber nicht. Wie also gewöhnt man dem + und dem * ab greedy zu sein. Wie bringt man sie dazu, beim ersten Auftreten des Ausdrucks der Ihnen unmittelbar folgt zu stoppen. Das geht recht einfach und sieht so aus:

<?
$string="hallo du Mayer, Meyer, Meier";
preg_match("/.*?(M..er)/",$string,$wort_in_runden_Klammern);
print $wort_in_runden_Klammern[1];
?>

Es wurde lediglich das Fragezeichen hinzugefügt, mit der Wirkung, dass der * (bzw. das + Zeichen) nach Auftreten des erstmaligen Auftretens des Ausdrucks der danach steht stoppt. Wir erhalten das, was viele wohl schon oben erwartet haben: Mayer.

Eine Wortgrenze festlegen

Der oben beschriebene Fall, der Ausdruck, der eine email Adresse beschreibt, war ja ganz nett. Aber was machen wir, wenn wir alle, also unter Umständen mehrere email Adressen aus einer HTML Seite fischen wollen. Wir können dann als Begrenzer des Ausdrucks nicht mehr das $ Zeichen verwenden, weil die Zeichenkette ja danach weitergeht. Eine Lösung sieht so aus:

<?
$string=" In einer HTML Seite können sich mehrere email Adressen befinden
wie z.B. Andres_Ehmann@web.de. Es kann sogar
komplizierter sein, die email Adresse kann clickable sein also
<A href=mailto:infos@infos24.de>infos@infos24.de</A>. Man weiss
auch nicht wieviele drin sind, z.B. bei Firmen kann ja eine da stehen,
wie etwa duisenberg@ezb.de oder eine ganze Latte,
willibald@ezb.com und kunigunde@ezb.de. Wir sehen also, es ist schwierig.";

$anzahl_der_Treffer=preg_match_all("!\b\w[\w|\.|\-]+@\w[\w|\.|\-]+\.[a-zA-Z]{2,4}\b!",
$string,$speicher_mails);
for($i=0;$i<$anzahl_der_Treffer;$i++)
{
print $speicher_mails[0][$i]."<br>";
}
?>

Das produziert dann dieses Ergebnis:

Andres_Ehmann@web.de
infos@infos24.de
infos@infos24.de
duisenberg@ezb.de
willibald@ezb.com
kunigunde@ezb.de

Es wurde also lediglich da Dach ^ und das Dollar Zeichen durch eine word boundary \b ersetzt. Nun stellt sich die Frage, welches Zeichen durch die word boundary \b eigentlich dargestellt wird. Die Antwort ist: Gar keines. Eine word boundary ist immer dann gegeben, wenn das Zeichen links davon ein word element ist also zur Gruppe \w gehörig und rechts davon ein non word charakter Zeichen steht. Es muss also nicht unbedingt ein Leerzeichen das sein. Dies kann man der Tatsache entnehmen, dass die email Adresse in infos@infos24.de gefunden wird. Das Zeichen \b ist selber aber kein Zeichen und die regular expression wandert durch eine word boundary auch nicht weiter.

Eine Gruppe negieren

Das Dach ^ haben wir schon kennengelernt. Normalerweise signalisieren wir damit, dass die regular expression der Zeichenkette, auf die sie angewendet wird, von Anfang an entsprechen muss. Das Dach hat aber innerhalb der Definition einer Gruppe eine völlig andere Bedeutung. Innerhalb einer Gruppe wird der Inhalt der Gruppe durch das Dach negiert.

<?
$string="Andres E§hmann";
$treffer=preg_match("/[^A-Za-zöüä\s]/",$string);
print $treffer;
?>

Mit einer regular expression, wie sie oben beschrieben ist, könnte man zumindest eine sehr grobe Art und Weise prüfen, ob der Namen plausibel ist. Namen, zumindest von natürlichen Personen, können nur Buchstaben und Leerzeichen enthalten. Die Besonderheiten der jeweiligen Sprache müsste man dann noch extra angeben. Die oben abgebildete regular expression würde nun aber nicht prüfen, ob einer der in der Klammern stehenden Zeichen in dem Ausdruck enthalten ist. Das Dach bewirkt, dass jedes Zeichen ein Treffer ist, das nicht enthalten ist. Da der Name ein Zeichen enthält, dass nicht enthalten ist, nämlich das § Zeichen, hat die Variable $treffer den Wert 1. Prüfen, ob ein lange Zeichenkette vorkommt, die keine Leerzeichen enthält
Ein typisches Problem der Internetprogrammierung ist die Notwendigkeit, lange Zeichenketten ohne Leerzeichen abzufangen. Dieses Problem stellt sich bei Gästebüchern, Chats, Foren, Anzeigenmärkten etc. Der User kann in ein HTML Formularfeld eine sehr lange Zeichenkette, z.B. 1000 Zeichen ohne Leerzeichen. Der Browser hat dann keine Chance, umzubrechen. Dies wiederum bewirkt, dass die komplette Zeichenkette in einer Zeile dargestellt wird, was dann wiederum den Broser veranlasst, nach rechts wegzuscrollen und das gesamte Layout der Seite zu zerschiessen. Mit dem in dem Skript unten enthaltenem Algorithmus liese sich dieses Problem lösen.


<?
$string="dasisteineZeichenketteohneeinLeerzeichendaswürdezu
problemenführendaderBrowserdieseineinerZeile
darstellenmüsstewodurchdasLayoutzerschossenwird";
$treffer=preg_match("/[^\s]{45}/",$string);
print $treffer;
?>

Das heisst, wir suchen eine 45 Zeichen lange Zeichenkette, in der jedes Zeichen ausser dem Leerzeichen \s vorkommen darf. Ist $treffer also 1, was hier der Fall ist, dann ist die Zeichenkette ungültig, da zu lang.

Unterscheidung zwischen Groß- und Kleinschreibung ausschalten

Wenn man nichts tut, wird zwischen Groß- und Kleinschreibung unterschieden, das heisst, unten stehendes Programm hat den Rückgabewert 0.

<?
$string="Andrés";
$treffer=preg_match("/a/",$string);
print $treffer;
?>

A ist nicht a und folglich ist die regular Expression in der Zeichenkette Andrés nicht vorganden. Das kann man mit i wie indifferent ändern.

<?
$string="Andrés";
$treffer=preg_match("/a/i",$string);
print $treffer;
?>

Das produziert dann dieses Ergebnis:

Jetzt erscheint 1 im Browser.

Mit regular expressions einen Array durchsuchen

Man kann mit regular expressions auch einen Array durchsuchen. Das Ergebnis ist dann wiederum ein Array, der die Arrayelemente enthält, die mit der regular expression übereinstimmen. Die Funktion entspricht der grep Funktion von Perl.

<?
$tutti=array("Banane","Himbeere","Ananas","Birne","Granatapfel","Pflaumen");
$treffer=preg_grep("/an/i",$tutti);
foreach($treffer as $gefunden)
{
print $gefunden. "<br>";
}
?>

Das produziert dann dieses Ergebnis:

Banane
Ananas
Granatapfel

Zeichenketten an einer Regular expression trennen

Man kann, insbesondere in der Bioinformatik, vor dem Problem stehen, dass man eine lange Zeichenkette in einzelne Bereiche auftrennen will, die Schnittstelle aber, an der gespalten werden soll, nicht bekannt ist. In diesem Fall kann man auch an einer regular expression spalten. Die Funktion entpricht der grep Funktion in Perl.

<?
$string="Andres Ehmann 11111 David Romero 22222 Jaime
Jimenez 33333 Maria Gonzales 44444 Consuelo Landivar";
$einzelteile=preg_split("/\d{5}/",$string);
foreach ($einzelteile as $einzeln)
{
print $einzeln."<br>";
}
?>

Das produziert dann dieses Ergebnis:

Andres Ehmann
David Romero
Jaime Jimenez
Maria Gonzales
Consuelo Landivar

Bestimmte Werte durch eine regular expression ersetzen

Will man dem User erlauben, Bilder in z.B. Gästebücher einzufügen, dann ist er meistens nur in der Lage, etwas wie http://www.eine_domain.de/bild.jpg einzugeben. Damit es tatsächlich erscheint, müsste das Bild eingebunden werden in einen HTML Tag, also . Man muss also eine Möglichkeit finden, ein Bild in einen HTML Tag einzubinden.

<?
$string="Bilder, wie etwa www.eine_domain.de/bilder/bild.gif,
machen alles richtig schön bunt. Geht auch mit http://www.domain.de/kirsche.jpg";
$ersetzt=preg_replace("!(http://|\s)([\w|-|_|/|\.]+/[\w|-|_]+\.
((jpg)|(gif)|(png)))!","<img src=http://$2>",$string);
print $ersetzt;
?>

Der HTML Quellcode,der produziert wird, sieht dann so aus:
Bilder, wie etwa<img src=http://www.eine_domain.de/bilder/bild.gif>, machen alles richtig schön bunt.
Geht auch mit <img src=http://www.domain.de/kirsche.jpg>

Wie deutlich zu sehen, wurde, der Pfad zu dem Bild in den entsprechenden HTML Tag eingebunden.
Auch dies ist mal wieder so eine regular expression, bei der es einem glatt die Schuhsohlen hochzieht. Machen wir uns das klar. Die regular expression lässt sich aufspalten in mehrere Bereiche.

(1) (http://|\s)
Vor der eigentlichen Adresse, müsste eigentlich http:// stehen. Wir wissen aber nicht,
ob der User genug Erfahrung mit dem Internet hat. Unter Umständen vergisst er dass,
so dass vor dem eigentlichen Link auch lediglich ein Leerzeichen stehen kann.
Wichtig an dieser Stelle, die runde Klammer. Die eckige Klammer hätte die Wirkung, dass jedes Zeichen zum anderen in einer oder Beziehung steht. Also h oder t oder p oder : oder /. Das ist nicht das, was wir wollen. Der Ausdruck als ganzes soll auftauchen, http:// oder das Leerzeichen \s. Die runde Klammer hat aber auch noch eine zweite Wirkung. Der Teil der Zeichenkette, der dem Teil des von der runden Klammer umfassten Teils der regular expression entspricht, wird in der Sondervariablen $1 bzw. $2, wenn es noch einen geklammerten Ausdruck gibt, bzw. $3 etc. abgespeichert. Man beachte, dass wir als zu ersetzenden Wert mit der Variablen $2 arbeiten.

(2) (reg ex)
Man beachte, dass alles was dann folgt, in runden Klammern steht, so dass wir es nachher mit $2 wieder abgreifen können.

(3) [\w|-|_|/|\.]+/
Wir greifen durch bis zum letzten /. Vorkommen dürfen alle word elements, siehe oben, der Bindestrich, der _ oder ein Punkt.

(4) [\w|-|_]+
Nach dem letzten slash, zu dem wir in (3) marschiert sind, kommt der Name des Bildes (im Beispiel bild). Er kann aus einem word element, einem Bindestrich oder einem Unterstrich bestehen. Dieser Ausdruck marschiert bis zu dem Punkt vor der Dateiendung (png, gif, jpg).

(5) ((jpg)|(gif)|(png))
Am Schluss muss entweder jpg, gif oder png stehen. Man beachte, dass der ganze Ausdruck nochmal von einer Klammer umfasst wird. Nur so erkennt die regular expression, dass entweder jpg oder gif oder png gefunden werden soll.

Die Funktion preg_replace

Die Funktion preg_replace hat folgende Syntax:
preg_replace("regular expression, die zeigt, was ersetzt werden soll","das, durch was ersetzt wird","die Zeichenkette, auf die sie angewendet wird); Interessantes und neues gibt es jetzt nur über den zweiten Parameter der Funktion zu berichten. In der regular expression haben wir die Adresse des Bildes in runde Klammern gesetzt. Folglich steht uns dieser Wert nun in der Sondervariablen $1 zur Verfügung. Wir verwenden diesen Wert, um den HTML Tag zusammenzubauen. Thats it.

Mehrere Teilstrings durch mehrere regular expressions ersetzen

Die Funktion preg_replace hat gegenüber der substitution Funktion von Perl den Vorteil, dass sie auch Arrays als Parameter akzeptiert. Dies ermöglicht es, auf eine Zeichenkette mehrere regular expression anzuwenden.

<?
$adresse=array("/Familienname/","/Telefon/","/Beruf/");
$ersatz=array("name","phone","profession");
$string="Familienname:Andres Ehmann, Telefon:030-47301386,
Beruf: Diplom Volkswirt/Magister Artium";
$fertisch=preg_replace($adresse,$ersatz,$string);
print $fertisch;
?>

Das produziert dann dieses Ergebnis:

name:Andres Ehmann, phone:030-47301386,profession: Diplom Volkswirt/Magister Artium

vorhergehendes Kapitel