<< Funktionen | Inhalt | Verzeichnisse und Dateien >> |
Jetzt wird's heiß ...
Ein regulärer Ausdruck ist ein Muster, das mit einer Zeichenkette verglichen wird. Oft wird ein regulärer Ausdruck dazu benutzt, um etwas bestimmtes zu suchen (z. B. einen Link in einer HTML-Seite) oder man will einen Teil einer Zeichenkette verändern, ...
Gekennzeichnet wird ein regulärer Ausdruck mit zwei // - alles was zwischen den beiden Slashes steht, ist das Muster.
Will man in einem String $text schauen, ob der Text hello enthält, sucht man nach dem Muster hello, wie folgt:
Neben dem Suchen kann man auch eine Ersetzung vornehmen und zwar mit dem Substitute-Operator: s/muster/ersetzen mit/;:
Die Zeichen \ | ( ) [ { ^ $ * + ? . / sind Sonderzeichen innerhalb eines regulären Ausdrucks (diese werden später noch erklärt). Wenn man diese in einem String sucht, so muss man einen Backslash \ davor setzen:
Normalerweise weiß man nicht exakt, welche Zeichen vorhanden sind. Bleiben wir bei dem Link in einer HTML-Seite: Dieser beginnt mit <a, dann kommt die Referenz (die man vielleicht kennt) und sonst irgendwas, bis zum >. Man weiß also recht wenig. Perl hat für Zeichen, die man nicht unbedingt kennt, den . eingeführt. . bedeutet: 'irgendein beliebiges Zeichen außer dem Newline ("\n")':
Jetzt können wir beliebige Zeichen darstellen. Wenn man eine bestimmte Auswahl von Zeichen vorgeben will (man will z. B. nur maler, maier und mayer finden), dann gibt es auch dafür eine Lösung. Man gibt eine sogenannte Zeichenklasse an, in der alle zulässigen Zeichen stehen. Sie wird mit [ eingeleitet und mit ] beendet:
Wie der . genau ein Zeichen repräsentiert, so auch eine Zeichenklasse: Genau ein Zeichen aus dem angegeben Möglichkeiten.
Will man eine Auswahl von Zeichen nicht haben (Negation), stellt man nach dem [ das Zeichen ^:
Um sich etwas Schreibarbeit zu sparen und natürlich auch die Übersicht zu behalten, kann man etwas wie [012345] auch schreiben als [0-5]. Das gilt auch für Buchstaben: statt [cdefghijklmnop] schreibt man kurz [c-p]. Folgendes ist auch möglich:
Es gibt spezielle Kürzel innerhalb der der regulären Ausdrücke - so wie der . -, die aber nur bestimmte Zeichen abdecken:
Kürzel | Entsprechung als Zeichenklasse | Beschreibung |
. | alle Zeichen außer "\n" | |
\d | [0-9] | eine Ziffer |
\D | [^0-9] | keine Ziffer |
\w | [a-zA-Z0-9_] | Buchstabe, Ziffer oder _ |
\W | [^a-zA-Z0-9_] | weder Buchstabe noch Ziffer noch _ |
\s | [ \n\t\r\f] | Sonderzeichen: Leerzeichen, Neuezeile, ... |
\S | [^ \n\t\r\f] | keines der Sonderzeichen |
Beispiele:
Die Sonderzeichen, die im regulären Ausdruck (s. o.: \ | ( ) [ { ^ $ * + ? . /) außerhalb der Zeichenklasse stehen, sind andere als die, die in der Zeichenklasse vorkommen. Letztere sind: $ - ] \ / ^. Auch diese werden mit Hilfe von einem Backslash \ darstellbar gemacht. Alle anderen Zeichen werden in der Zeichenklasse auch so interpretiert; das gilt auch für den .; d.h., dass /[,.]/ nach einem , oder einem . in der Zeichenkette sucht.
Will man nun testen, ob ein Wort in der Zeichenkette ist der Form: hao oder halo oder hallo oder halllo oder hallllo oder ... hallo mit beliebig vielen l in der Mitte, dann benutzt man einen * im regulären Ausdruck:
Mit obigen Multiplikatoren kann man einiges anstellen! Hier sind einige Beispiele aus den man lernen kann.
Würde man statt /m*/ /m+/ schreiben, sucht Perl nach mindestens einem m; d. h., im String wäre dann hakxxxxxol. Daran kann man erkennen, dass Perl recht gefräßig ist. Gibt man ein + oder * an, so holt sich Perl, falls die erste Übereinstimmung gefunden wurde, soviel, wie nur geht. Man kann diese Gefräßigkeit (ab der Version 5) unterbinden, indem man nach dem + oder * ein ? setzt:
Ein gutes Beispiel für das ? liefert unsere HTML-Referenz <a href="www.mathe2.uni-bayreuth/perl/start.htm" target="_blank">.
Wir möchten einen String, wie z. B. "www.mathe2.uni-bayreuth/perl/start.htm", finden. Das heißt, wir suchen ein " anschließend beliebig viele Zeichen bis zum nächsten ":
Ein weiteres Beispiel: Wir möchten wissen, ob in der Seite, die in der Variablen $seite gespeichert ist, ein Link existiert. Kriterien dafür sollen sein:
Mit Hilfe von runden Klammern () können wir uns auf mehr als ein Zeichen in regulären Ausdrücken beziehen, falls man zum Beispiel einen längeren Ausdruck mehrfach sucht:
Mit runden Klammern kann man nicht nur beliebige Zeichen, sondern auch einen beliebigen Teil des regulären Ausdrucks zusammenfassen:
Es gibt noch einen Nebeneffekt: Perl speichert die gefunden Ergebnisse beim Mustervergleich ab und zwar in die Variablen: $1 für die erste Klammerung, $2 für die zweite Klammerung, etc. Es zählt dabei die linke Klammer ( der Klammerung; bei Verschachtelung kann es dann keine Schwierigkeiten geben:
Das passiert:
Es ist sogar möglich, schon innerhalb des regulären Ausdrucks auf den Inhalt von $1, etc. zuzugreifen. Jedoch muss dort statt dem $-Zeichen der Backslash \ verwendet werden: also z. B.: \1:
Wir suchen in einem String zwei gleiche Zeichen hintereinander und möchten dieses ausgeben:
Im Zusammenhang mit \1, etc. kann es zu Schwierigkeiten kommen (vgl. Oktalzahl):
Will man verhindern, dass der Wert einer Klammerung einer Variablen z. B. $1 zugewiesen wird, so muss man ein Fragezeichen mit einem Doppelpunkt ?: nach der Klammer setzen:
Bis war es nur möglich irgendwo im String schauen, ob das Muster passt. Will man dies sofort am Anfang testen, so muss man ein ^ als erstes Zeichen im regulären Ausdruck setzen (das nennt man dann auch Anker):
Analog kann man einen Mustervergleich am Ende eines Strings durchführen mit einem $ am Ende des regulären Ausdrucks:
Statt ^ und $ kann man auch fast immer \A und \Z verwenden. Der einzige Unterschied ergibt sich bei der Option m - siehe unten.
Es gibt noch etwas spezielles. Mit \b kann man festlegen, dass an dieser Stelle eine Wortgrenze vorliegt. Das ist ein Übergang von einem Wort (also \w) zu einem Nichtwort (\W) bzw. ein Übergang von einem Nichtwort zu einem Wort. \b kann aber auch Stringanfang oder Stringende bedeuten. Dabei repräsentiert \b kein Zeichen! Mit \B ist wieder das Gegenteil gemeint. Hier ein paar Beispiele:
Mit dem Oder-Operator | kann man Perl in einem regulären Ausdruck mehrere Alternativen zur Verfügung stellen:
Auch in regulären Ausdrücken ist es möglich, dass es nicht eindeutige Ausdrücke gibt (analog zu dem Problem: Was ist 3+5*7). Eigentlich ist schon im Beispiel vorher unklar, ob Perl nach C, Pascal oder Perl sucht oder nach CascalerlDatenbankanbindungen, CascaPerl, Pascalerl oder PascaPerl. Deshalb wurde auch innerhalb von regulären Ausdrücken eine Rangfolge festgelegt:
Name | Operator |
runde Klammern | () |
Multiplikatoren | + * ? {m} {m,n} {m,} |
Zeichen, Anker | abc123.[irgendwas]\d\w\s ^ \b \B $ |
Oder, Alternative | | |
Damit ist auch geklärt, warum das Beispiel mit den Programmiersprachen auch so funktioniert, wie es soll: Zeichen bzw. ganze Zeichenfolgen haben höheren Rang als der Oder-Operator. Noch ein Beispiel:
Kürzer geht's natürlich so ...
Und noch kürzer geht's so (leider ohne oder) ...
In einem regulären Ausdruck können auch Variablen eingesetzt werden. Diese werden bevor gesucht wird, ersetzt mit dem Inhalt der Variablen. Wenn ich also nach einem Muster \d+ suchen will, kann ich das auch so tun:
Obiges Beispiel noch einmal (etwas umständlich), um zu zeigen, was möglich ist:
Einem regulären Ausdruck können auch Optionen übergeben werden. Dadurch wird das Verhalten z. B. beim Suchen oder Ersetzen verändert. Hier eine Tabelle:
Option | Beschreibung |
i | Groß- und Kleinschreibung ignorieren (case-insensitive) |
g | globale Suche (global) |
s | das Sonderzeichen \n wird nicht getrennt betrachtet (single line) |
x | ermöglicht, komplizierte reguläre Ausdrücke - was ziemlich schnell geht - über mehrere Zeile auszudehnen und Kommentare einzufügen (extended) |
m | Perl betrachtet ^ und $ nicht nur für Stringanfang und -ende, sondern auch für Zeilenanfang und -ende (multiple lines). Für \A und \Z hat diese Option keine Auswirkungen. |
e | diese Option kann nur beim Ersetzen (s///) in einem String verwendet werden; der zweite Teil im Substitute-Operator also alles zwischen zweiten und dritten Slash / wird dann nicht als Zeichenkette interpretiert, sondern als (evaluate) |
Beispiele dazu:
Der Operator split() zerlegt mit Hilfe eines regulären Ausdrucks eine Zeichenkette. Zurückgegeben wird ein Array. Die Syntax lautet split(/regulärer Ausdruck/,Zeichenkette):
Der Operator join() verknüpft Zeichenketten. Die Syntax lautet join(Zeichenkette, Array). Dabei werden die Elemente des Arrays zusammengeklebt. Zwischen den einzelnen Elementen steht aber die Zeichenkette. Als Ergebnis liefert der join-Operator einen String:
<< Funktionen | Inhalt | Verzeichnisse und Dateien >> |
© 2001-2003 Perl, Lehrstuhl Mathe II, Uni Bayreuth |