Homepagebau
Dateiversion:
diesen Beitrag diskutieren,
ergänzen, eine Frage stellen

Regular Expressions

Schwierigkeitsgrad:

Kompatibilität: Perl 5, JavaScript 1.2, JScript (ab IE 5.0), PHP 4

Was ist das?

Dieser Artikel will ihnen ein mächtiges Werkzeug der Programmierkunst näher bringen. Es steht ihnen sowohl in Perl, JavaScript und PHP als auch in vielen anderen Sprachen zur Verfügung. Die Syntax ist in allen Programmiersprachen gleich, erfordert jedoch etwas Übung.

Weil die Schreibweisen sehr ähnlich sind, werden hier PHP, JavaScript und Perl gleichzeitig abgehandelt. Jedoch ohne näher auf die Details und Feinheiten der einzelnen Sprachen einzugehen.

Reguläre Ausdrücke sind dazu da, das Suchen und Ersetzen von Textstellen in Strings zu erleichtern. Informatiker kennen das sicher aus der Uni oder dem Unterricht. Es handelt sich um die formale Sprache, um die Syntax eines Textes zu beschreiben. Ein regulärer Ausdruck kann wie ein Suchmuster gebraucht und auf einen längeren Text angewendet werden um solche Textstellen zu finden, welche der durch ihn beschriebenen Syntax genügen.

Angenommen sie haben eine HTML-Seite in einen String kopiert und möchten gern eine Auflistung aller enthaltenen Hyperlinks... dann ist das mit Hilfe des richtigen regulären Ausdrucks in einer einzigen Zeile Code bereits geschafft, während sie mit klassischen Mitteln ein sehr langes, unübersichtliches Durcheinander von Anweisungen benötigt und jede Menge Zeit dadurch verschwendet hätten.

Definition

zum Beispiel: A, ab, 1900, Anno 2003

zum Beispiel: (), [], (a), [b], (abc), (10AxV), (a B 9), [abc], [10AxV]

zum Beispiel: (a*), [b]+, (a+)[b]?, (abc)*, [AB]+cd, a?bc, 10*a

zum Beispiel: a{1} (= a), oder a{5,10} (5-10 a's), (ab){,5}

zum Beispiel: (a|b)*, Theres(e|a), M(a|e)(i|y)e?r

Bedeutung

Reguläre Ausdrücke werden üblicherweise von Trennzeichen (/) begrenzt:
/reg. Ausdruck/

Jedes normale Alphanumerische Zeichen (also A-Z, a-z und 0-9 ) steht für genau dieses Zeichen
/ABBA/ steht ganz einfach für ABBA
//
steht für nichts

Der Punkt . steht für ein beliebiges Zeichen
/./ steht für a oder b oder 0 oder # oder Leerzeichen usw.
/.bc/
steht für ein Wort mit 3 Buchstaben, dass auf bc endet 
/a.*/ steht für alle Texte, die mit a beginnen
/.*a/ steht für alle Texte, die auf a enden
/.*/ steht für alles

Die Zeichen ? * + sind so genannte "Quantoren" oder "Mengenzeichen"
/a?/ steht für nichts oder a
/a+/ steht für a oder aa oder aaa usw.
/a*/ steht für nichts oder a oder aa oder aaa usw.

Hinweis:

Achtung! Die Quantoren *, + und ? stehen stets für die maximale Anzahl. Zum Beispiel a* bei Eingabe aaab also für aaa und NICHT für a oder aa. Und [ab]*ab bei Eingabe ababc für abab und nicht für ab !!!

Einen Quantor mit dieser Eigenschaft nennt man "gierig" (eng. greedy). Um nur die minimale Anzahl zu finden kombinieren sie den Quantor mit '?'. Zum Beispiel a*?, a+? oder a??

Leider funktioniert das nur in Perl, JavaScript und JScript ab IE 5.5. In PHP ist dies NICHT möglich: hier müssen sie den Modifikator /U verwenden (wie das geht steht im Abschnitt über Modifikatoren)

Das Zeichen | steht für "oder". Das heißt, es kann entweder den Ausdruck links oder den rechts davon bedeuten.
/a|b/ steht für a oder b
/Theres(e|a)/ steht für Therese oder Theresa
/M(a|e)(i|y)er/ steht für Maier, Mayer, Meier oder Meyer

Die Klammern [] stehen für "eines der enthaltenen Zeichen"
/[abc]/ steht für a oder b oder c
/[abc]?/ steht für nichts oder a oder b oder c
/[abc]*/
steht für nichts oder a oder b oder c oder
ab oder aa oder
ac oder aba oder ccc oder caab usw.

Die Klammern () haben neben ihrer offensichtlichen Funktion noch eine andere Anwendung. Sie dienen dazu, eine Fundstelle zu markieren. Das ist sinnvoll, falls Text nur dann gefunden werden soll, wenn er nach oder vor einem bestimmten anderen Text steht.
/a(bc)d/ steht für bc nach a und vor d
/Alphabet:(abc)def/ steht für alle abc nach "Alphabet:" und vor "def"

Falls sie eine Textersetzung durchführen können sie auf diese in Klammern gesetzte Fundstellen innerhalb des regulären Ausdrucks auch direkt Bezug nehmen, was gelegentlich sehr sinnvoll ist: $0 steht für den gesamten Treffer, $1 steht dann für den ersten geklammerten Ausdruck, $2 für den zweiten, $3 für den dritten usw.

Beispiel:
angenommen ihr reg. Ausdruck lautet /text ((a) text (b)) text (c)/
dann gilt $0 = text a text b text c, $1 = (a text b), $2 = (a), $3 = (b), $4= (c)
Bitte beachten: in PHP müssen sie statt $0, $1, $2, ... \\0 \\1, \\2, ... schreiben

Wenn sie eines der Zeichen wie ?+*()[]/|. als Text suchen wollen, müssen sie vor dieses Zeichen ein "\" setzen. Das bezeichnet man als "Escape-Sequenz".
/\(abc\)/ steht für (abc)

Zusammenfassung

reg. Ausdruck Bedeutung
a steht für "a"
a* 0 oder n-mal
a+ 1 oder n-mal
a? 0 oder 1-mal
a*? 0 oder n-mal (ungreedy) IE ab 5.5, nicht in PHP
a+? 1 oder n-mal (ungreedy) IE ab 5.5, nicht in PHP
a?? 0 oder 1-mal (ungreedy) IE ab 5.5, nicht in PHP
a{n} genau n-mal
a{n,} mind. n-mal
a{,n} höchstens n-mal
a{n,m} mind. n-mal und höchstens m-mal
[abc] eines der genannten Zeichen
[^abc] jedes, AUSSER den genannten Zeichen
[a-z] alle Kleinbuchstaben
[A-Z] alle Großbuchstaben
[0-9] alle Ziffern
[^a-zA-Z] alles außer den Buchstaben

Wildcards

Mit Wildcards können sie sich Schreibarbeit sparen. Sie stehen jeweils für eine Sammlung von Zeichen.

Wildcard Alternative Bedeutung
. steht für ein beliebiges Zeichen
\d [0-9] eine Ziffer
\D [^0-9] alles außer einer Ziffer
\w [a-zA-Z_0-9] ein Wortzeichen (alphanumerisch)
\W [^a-zA-Z_0-9] alles außer einem Wortzeichen
\s [ \n\t\r\f] Whitespace (Leerzeichen, Zeilenumbrüche...)
\S [^ \n\t\r\f] alles außer einem Whitespace-Zeichen
\b findet den Anfang/Ende eines neuen Wortes
\B alles außer einem Wortanfang oder -ende
\A ^ steht für den Anfang des Strings:
für Begriffe, die direkt am Anfang einer Zeile stehen müssen
\z $ steht für Zeilenende oder Ende des Strings:
für Begriffe, die direkt am Ende einer Zeile stehen müssen
\Z steht für das Ende des Strings

Modifikatoren

Das sind Zeichen, die hinter einen regulären Ausdruck geschrieben werden können, um die Auswertung zu beinflussen.
Zum Beispiel: /reg. Ausdruck/igs

Modifikation Bedeutung
g "global": globale Suche (findet alle Treffer) nicht in PHP
o "once": der Ausdruck wird bei mehrfacher Verwendung nur einmal kompiliert
nicht in PHP
in PHP verwenden sie statt dessen "S"
i "ignore case": Groß- Kleinschreibung wird beim Vergleichen ignoriert
s "single line": Zeilenumbrüche werden ignoriert
m "multi line": String wird Zeilenweise verglichen (Zeilenumbrüche werden beachtet)
x "eXtended": Whitespace-Zeichen werden ignoriert
U nur in PHP: alle Quantoren werden als "nicht gierig" ausgewertet.

Suchen und Ersetzen

Einen String nach einem Muster durchsuchen:
Perl: $String =~ m/MUSTER/modifikatoren
JavaScript: var stringArray = string.match(/MUSTER/modifikatoren);

oder:
var myRegExp = /MUSTER/modifikatoren;
var stringArray = myRegExp(string);

oder:
var myRegExp = new RegExp("MUSTER");
var treffer = myRegExp.exec(string);

PHP: $zahl = preg_match(/MUSTER/modifikatoren, $String, $stringArray);

$zahl = preg_match_all(/MUSTER/modifikatoren, $String, $stringArray);

Die Funktionen liefern true falls das Muster enthalten ist und sonst false.

Perl: Treffer werden in einem globalen Array gespeichert.
Die Elemente können über $i abgerufen werden.
"i" ist die Nummer des Treffers. $1 erster Treffer $2 zweiter Treffer usw.

JavaScript: Treffer werden bei String.match() als Array zurückgegeben.
Das erste Element des Arrays ist der erste Treffer, das zweite der zweite Treffer usw.

Die anderen beiden Beispiele nehmen einen String als Eingabe und liefern nur die erste Fundstelle in Form eines String als Ausgabe. Wenn sie die Funktion mehrmals mit dem gleichen Parameter aufrufen liefern sie danach die 2.,3.,4.,... Fundstelle oder NULL wenn nichts gefunden wurde. Das ist gelegentlich praktisch, weil sie so die einzelnen Fundstellen in einer Schleife durchlaufen können.

PHP: Die Treffer werden an das angegebene Array "$stringArray" übergeben.
Bei preg_match() ist dieser Parameter optional

 
Einen Teilstring ersetzen:
Perl: $String =~ s/MUSTER/ERSATZ/modifikatoren
JavaScript: var stringArray = string.replace(/MUSTER/modifikatoren, "ERSATZ");
PHP: $string = preg_replace(/MUSTER/modifikatoren, "ERSATZ", $string);
Die Funktionen liefern true falls eine Ersetzung stattgefunden hat und sonst false.

Tipp: sie können auch Teile des MUSTERs in Klammern setzen. Dadurch können sie Zugriff auf einzelne Teile des Musters erlangen.
Zum Beispiel ersetzt der folgende Ausdruck alle "B"-Tags durch "STRONG"-Tags /<B>(.*?)<\/B>/<STRONG>$1<\/STRONG>/

Perl und JavaScript: $0 gibt die gesamte Fundstelle an.
$1, $2, $3, ... beziehen nur auf die Teile der Fundstelle, innerhalb der 1., 2., 3., ... runden Klammern

PHP: fast identisch zu Perl und JavaScript. allerdings müssen sie statt $0,$1,$2,... hier \\0,\\1,\\2,.. schreiben

Beispiele

alle Whitespace-Zeichen in Leerzeichen umwandeln
Perl: $string =~ s/\s/ /g
JavaScript: var string = string.replace(/\s/g, " ");
PHP: $string = preg_replace(/\s/, "", $string);
 
Zeilenumbrüche in "<BR>" umwandeln:
Perl: $string =~ s/\n/<BR>/gs
JavaScript: var string = string.replace(/\n/gs, "<BR>");
PHP: $string = preg_replace(/\n/s, "<BR>",$string);
 
Die URLs aller Hyperlinks in einem HTML-Dokument finden:
Perl: $htmlDokument=~ m/<a.+?href="?(.+?)"?.+?>/gis
JavaScript: var stringArray = htmlDokument.match(/<a.+?href="?(.+?)"?.+?>/gis);
PHP: preg_match_all(/<a.+href="?([^"]+)"?.+>/Uis, $htmlDokument, $stringArray);
 
Alle Kommentare aus einem HTML-Dokument entfernen:
Perl: $htmlDokument=~ s/<\!\s*--.*?-->//gs
JavaScript: var htmlDokument = htmlDokument.replace(/<\!\s*--.*?-->/gs, "");
PHP: $htmlDokument = preg_replace(/<\!\s*--.*-->/Uis, "", $htmlDokument );
 
Alle Wörter farbig hervorheben, welche ein "a" enthalten
Perl: $htmlDokument=~ s/\w*a\w*/<span style="background:yellow">$0<\/span>/igs
JavaScript: var htmlDokument = htmlDokument.replace(/\w*a\w*/igs, '<span style="background:yellow">$0</span>');
PHP: $htmlDokument = preg_replace(/\w*a\w*/is, "<span style=\"background:yellow\">\\0</span>", $htmlDokument );
 
Alle <B> Tags in <STRONG> Tags umwandeln
Perl: $htmlDokument=~ s/<b>(.*?)<\/b>/<strong>$1<\/strong>/igs
JavaScript: var htmlDokument = htmlDokument.replace(/<b>(.*?)<\/b>/igs, '<strong>$1</strong>');
PHP: $htmlDokument = preg_replace(/<b>(.*)<\/b>/Uis, "<strong>\\1</strong>", $htmlDokument );