|

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
<?
$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.
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
|
 |