zurückInhaltvorwärts Perl Einführung: Reguläre Ausdrücke

7. Reguläre Ausdrücke

Bei den regulären Ausdrücken handelt es sich um eine Spezialität von Perl. Reguläre Ausdrücke sind auch sicher einer der Hauptgründe, warum viele Leute, die anfängen Perl zu lernen, es schnell wieder aufgeben. Was sind reguläre Ausdrücke? Reguläre Ausdrücke sind nichts anderes als Muster, mit denen man den Aufbau von Zeichenketten beschreiben kann. Ein regulärer Ausdruck ist also eine Beschreibung, die auf eine ganze Klasse von Zeichenketten paßt. Im Prinzip kennst Du bereits einfache reguläre Ausdrücke, die Du wahrscheinlich ohne zu überlegen angewendet hast, als Du auf der DOS Kommandozeile Befehle wie DIR *.EXE oder DIR SYS* eingeben hast. Das Jokerzeichen * ist hierbei ein Platzhalter für eine beliebige Anzahl beliebiger Zeichen, so daß der erste DOS Befehl soviel heißt wie liste alle Dateien auf, die die Endung EXE haben. Der Zweite DOS Befehl ist etwas einschränkender, er listet alle Dateien und Verzeichnisse auf, die mit der Zeichenkette SYS beginnen, auf die dann eine beliebige Anzahl beliebiger Zeichen folgen kann. Führt man also den Befehl aus, könnte das folgende Listing mit Dateien und Verzeichnissen erscheinen:

SYS.EXE
SYSCOM.DOC
SYSTEM.SYS
SYSSYS.TXT
SYSTER.COM
SYSTEM
SYSTEM32
SYS

Alle diese Datei- und Verzeichnisnamen fangen mit SYS an. Alle anderen Zeichen sind beliebig. Die regulären Ausdrücke, die Du angewendet hast sind also *.EXE und SYS*, die eine allgemeine Klasse von Datei- bzw. Verzeichnisnamen beschreiben. In Perl können reguläre Ausdrücke wesentlich komplexer sein als diese einfachen Beispiele - und sie sind es häufig auch. Bleiben wir bei dem letzten Beispiel für reguläre Ausdrücke in DOS, das SYS* Beispiel. Wie Du Dir sicherlich denken kannst, schreibt man reguläre Ausrücke in Perl etwas anderes. Als erstes stehen alle regulären Ausdrücke in slashes, d.h. //. In unserem Beispiel würden wir also als vorläufige Version /SYS*/ erhalten. Will man in einem regulären Ausdruck andeuten, daß beliebige Zeichen beliebig oft vorkommen dürfen, benutzt man den Punkt, ., und den Stern, *. Der Punkt steht für ein beliebiges Zeichen, der Stern für ein beliebig häufiges Vorkommen des unmittelbar davorstehenden Zeichens. Unser vollständig übersetztes Beispiel lautet also /SYS.*/ . Hier ein weiteres Beispiel, das den Gebrauch des Punktes in regulären Ausrücken vedeutlicht:

/mar.o/

Dieser reguläre Ausdruck paßt auf alle Zeichenketten, die mit mar beginnen, worauf dann ein beliebiges Zeichen folgt und schließlich mit einem o endet. Hier einige Zeichenketten, auf die der reguläre Ausdruck paßt:

marco, marko, margo, marzo.

Zeichenketten, auf die der reguläre Ausdruck nicht paßt:

marcko, marrko

Was passiert nun, wenn die Zeichenkette länger ist? Perl untersucht von links beginnend die Zeichenkette auf Übereinstimmung mit dem regulärem Ausdruck. Wenn eine Übereinstimmung gefunden wird, wird der Vergleich als wahr gewertet. Die folgenden Zeichenketten passen daher auch auf den regulären Ausdruck /mar.o/:

amarco, schmargo, pmarko, ammarkoni, pmarkomar

Aufbau von regulären Ausdrücken

In den meisten Fällen repräsentieren Zeichen in regulären Ausdrücken sich selbst. Ein a in einem regulärem Ausdruck paßt also auf ein a in einer zu durchsuchenden Zeichenkette, ebenso paßt eine Zeichenfolge dfd3434 in einem regulärem Ausdruck auf ein Vorkommnis der Zeichenkette dfd3434 in der zu durchsuchenden Zeichenkette.

Zeichen, die sich nicht selbst repäsentieren zeigt die folgende vollständige Liste

\ | ( ) [ { ^ $ * + ? .

Diese Zeichen haben Sonderbedeutungen. Die Bedeutung des Punktes haben wir bereits oben erklärt: Ein beliebiges Zeichen. Wir werden jetzt nacheinander die Bedeutung dieser Zeichen diskutieren.

Das Zeichen ^ in einem regulärem Ausdruck steht für den Anfang der Zeile:

/^Henning/ paßt auf folgende Zeichenketten:

Henning Rowlin
Henning bla bla

aber nicht auf:

Rowlin, Henning
bla bla Henning

Eine einzelne Zeichenkette kann auch mehrere Zeilen beeinhalten, deshalb ist das ^ nicht gleichbedeutend mit Anfang der Zeichenkette. Der reguläre Ausdruck /^Henning/ würde also auch auf den Inhalt der Variablen $var im folgenden Beispiel passen, das Zeichen \n steht hierbei für ein Newline Zeichen (entspricht dem drücken der <RETURN> Taste).

$var = "Hallo\nHenning";

Auf das Zeilenende kann man mit dem $ Zeichen prüfen. /Henning$/ paßt also auf folgende Zeichenketten:

Rowlin, Henning bla bla Henning

Bei folgenden Zeichenketten paßt dies nicht:

Henning Rowlin Henning bla bla

Hierbei ist auch wieder zu beachten, daß sich eine Zeichenkette auch über mehrere Zeilen erstrecken kann. /Henning$/ würde also auch auf den Inhalt der Variablen $var im nächsten Beispiel passen:

$var = "Hallo Henning\nund noch eine Zeile";

Zeichenwiederholungen

Möchte man auf mehrfaches Vorkommen eines Zeichens prüfen gibt es verschiedene Möglichkeiten. Folgt hinter einem Zeichen ein + Zeichen, bedeutet dies mindestens ein Vorkommen des Zeichens in der zu prüfenden Zeichenkette.

/hal+o/ paßt also auf folgende Zeichenfolgen:

hallo
halo
halllo
yxxxhalloxxxx
zhallllllllllo
hallo

Neben dem + gibt es noch das * als Wiederholungszeichen, hierbei kann das Zeichen vor dem * mehrfach vorkommen, es muß allerdings nicht vorkommen. So paßt /hal*o/ neben den Zeichenketten im letzten Beispiel auch auf:

hao

Will man auf ein null oder einmaliges Vorkommnis eines Zeichens in einer zu untersuchenden Zeichenkette prüfen, verwendet man das ? Zeichen. Der reguläre Ausdruck /pm?.rco/ paßt auf

pmarco
parco
pmrco

aber nicht auf die Zeichenkette

pmmarco

Man kann auch auf eine exakte Anzahl von Zeichenwiederholungen prüfen sowie eine Mindest- und Höchstanzahl von Zeichenwiederholungen vorgeben. Man benutzt hierzu die geschweiften Klammern {}, die dem betreffenden Zeichen nachgestellt werden.

Damit /ma{2}rco/ paßt müssen in der Zeichenkette genau zwei a vorkommen:

maarco
plmaarco
xxmaarconi

Damit /ma{2,}rco/ paßt müssen in der Zeichenkette mindestens zwei a vorkommen:

maarco
plmaarco
xxmaarconi
maaarco
hallo maaarco

Damit /ma{2,4}rco/ paßt müssen in der Zeichenkette mindestens zwei a vorkommen, aber maximal vier.

Die folgende Tabelle faßt das Gesagte zusammen:

*        	kein mal oder beliebig oft
+               mindestens einmal
?               einmal oder kein mal
{n}             genau n-mal
{n,}            mindestens n-mal
{n,m}           mindestens n-mal, aber maximal m-mal

Gruppierungen

Ihr habt euch vielleicht gefragt, wie man die +, * und ? Zeichen auf mehrere Zeichen anwenden kann. Hierzu verwendet man runde Klammern (), mit denen man mehrere Zeichen gruppieren kann.

/(mar)+/ paßt auf
marco
marmarco
mmarco
mmarmarco
markko
/h(al)*lo/ paßt auf
hallo
hlo
halallo
halalallo

/ha(ll)?o/ paßt auf

hallo
hao

Auswahlen von Zeichen

Eine Liste von Zeichen in eckigen Klammern bietet eine Auswahl aus diesen Zeichen an, auf die der reguläre Ausdruck passen kann. Der Audruck in eckigen Klammern steht nur für ein Zeichen aus der Liste. Das Beispiel /mar[ck]o/ paßt zum Beispiel auf die Zeichenketten

marco
marko

aber nicht auf

marcko

Das Beispiel /m[ea][iy]er/ paßt auf

meier
meyer
maier
mayer

Will man eine Auswahl aus einem Ziffernbereich oder einem Bereich des Alphabets treffen, bedient man sich des - Zeichens.

Das Beispiel /[a-z]+/ paßt auf alle Kombinationen aus kleinen Buchstaben, die beliebig oft aber mindestens einmal vorkommen müssen.

/[A-Z][a-z]+/ paßt auf alle Kombinationen aus Buchstaben, die mit einem großen Anfangsbuchstaben beginnen und und von einer beliebgen Anzahl kleiner Buchstaben gefolgt werden.

/[0-9]{5}/ paßt auf alle fünfstelligen Dezimalzahlen.

Alternativen

Mit dem Operatorzeichen | kann man in einem regulärem Ausdruck mehrere alternative Zeichenketten angeben, auf die eine bestimmte Zeichenkette untersucht werden soll.

/^(M|m)arco/ paßt auf alle Zeichenketten, die mit einem großem M ODER einem kleinem m beginnen, worauf die noch die Zeichenkette arco folgt. Das Beispiel paßt also auf:

Marco
marco

/(herr|frau) mayer/ paßt also z.B. auf die Zeichenketten

herr mayer
frau mayer

Die Besprechung der Sonderzeichen wollen wir an dieser Stelle beenden und uns einer Frage zuwenden, die Ihr euch vielleicht die ganze Zeit über gestellt habt: Was ist, wenn man in einer Zeichenkette z.B. nach einem ? oder einem + sucht? Wendet man diese Zeichen in einem regulärem Ausdruck an, so haben sie spezielle Bedeutungen, wie wir sie bereits weiter oben diskutiert haben. Die Lösung ist ganz einfach, führt jedoch dazu, daß der reguläre Ausdruck nicht mehr ganz so gut lesbar ist: Man stellt dem Sonderzeichen einfach ein \ voran. Stellt euch vor ihr sucht in einem Text entweder nach der email Adresse marco@tekromancer.com oder henning@tekromancer.com. Das Problem ist einzig der Punkt, der sonst die Bedeutung "beliebiges Zeichen" hat und hier sich selbst repräsentieren soll. Hier ist die Lösung:

/(marco|henning)@tekromancer\.com/ paßt also auf

marco@tekromancer.com
henning@tekromancer.com

Weitere Operatoren

Buchstaben denen ein Backslash vorangestellt wird, kennzeichnen Sonderzeichen oder bestimmte Zeichenklassen. Hier eine (fast) vollständige Liste:

\t	paßt auf einen Tabulator
\r	paßt auf ein Carriage Return
\f	paßt auf einen Formfeed
\d	paßt auf eine Ziffer

\D	paßt auf alle Zeichen außer Ziffern

\w	Wortzeichen, also alle Zeichen von a bis z (in Groß- und Kleinschrift), Ziffern (0-9) und den Unterstrich _

Stelle Dir vor, Du suchst beliebige Wörter mindestens der Länge 5, dann könntest Du folgendes schreiben:

/\w{5,}/ paßt auf

marco
xyzab
s_ddh
12mar
1_2_3
\W	Kein Wortzeichen

\s	paßt auf Leerzeichen, Tabulator, Newline, Carriage Return, Formfeed
\S	paßt auf auf alles außer Leerzeichen, Tabulator, Newline, Carriage Return, Formfeed

\A	paßt auf den Anfang einer Zeichenkette
\Z	paßt auf das Ende der Zeichenkette

\b	paßt auf eine Wortgrenze


z.B. paßt /marco\b/ auf
adjsdakmarco hallo
marco

aber nicht auf

marcoxxxx
jhgjhgjhmarco4554535

Ferner paßt /\bmarco\b/ auf

marco
@marco% (@ und % sind KEINE Wortzeichen, siehe obige Definition von \w)
&marco? (& und ? sind KEINE Wortzeichen, siehe obige Definition von \w)

aber NICHT auf

3243243marco
marcofasdfad
23423marco32432423

Modifikatoren

Wie führt man nun eine Suche durch, die nicht auf Groß- und Keinschrift achtet? Hierzu kann man einen Modifikator verwenden, Modifikatoren werden einfach an den regulären Ausdruck gehängt.

/marco/ paßt, wie ihr bereits wißt, auf alle Zeichenketten, die marco enthalten, also auf

marco
dsfasdfmarcokjkljl
323223marco213123
dsfadsmarco

/marco/ paßt aber nicht auf

MARCO
3214324MARCO
MArco

Wenn man bei der Suche nach marco die Groß- und Kleinschreibung ignorieren will, muß man folgendes tun

/marco/i

Das i steht für ignore (=ignorieren) und bezieht sich auf die Groß- und Kleinschreibung. Es gibt noch weitere Modifikatoren, auf die werden wir hier aber nicht näher eingehen.

Perl Einführung: Reguläre Ausdrücke zurückInhaltvorwärts