SELFHTML

Reguläre Ausdrücke

Informationsseite

nach unten Allgemeines zu regulären Ausdrücken
nach unten Reguläre Ausdrücke anwenden
nach unten Reguläre Ausdrücke für einzelne Zeichen
nach unten Reguläre Ausdrücke für Zeichenketten
nach unten Maskierung von Zeichen in regulären Ausdrücken
nach unten Gierige und genügsame Suchmuster
nach unten Reguläre Ausdrücke mit Alternativen
nach unten Teilausdrücke merken mit Klammerung
nach unten Rangfolge in regulären Ausdrücken
nach unten Flags hinter regulären Ausdrücken
nach unten Suchen und Ersetzen mit regulären Ausdrücken
nach unten Transliteration

 nach unten 

Allgemeines zu regulären Ausdrücken

Reguläre Ausdrücke sind genau definierte Suchmuster. Mit Hilfe dieser Suchmuster können Sie beispielsweise Variableninhalte durchsuchen und bestimmte Inhalte daraus herausziehen oder ersetzen. So können Sie mit Hilfe von regulären Ausdrücken etwa beim Einlesen von Dateien (z.B. einer Datei mit Einträgen eines Gästebuchs) anhand der Konventionen, nach denen die Datei aufgebaut ist, die einzelnen Einträge geordnet einlesen und als HTML-Code an den aufrufenden WWW-Browser übertragen. Reguläre Ausdrücke sind auch ein mächtiges Mittel, um große Datenbestände nach komplexen Suchausdrücken zu durchforsten.

Reguläre Ausdrücke sind allerdings für Neulinge, die nicht aus der Unix-Welt kommen, sehr ungewohnt und der Hauptgrund dafür, warum in manchen Perl-Scripts ziemlich merkwürdige, kryptisch anmutende Zeichenfolgen vorkommen. Wer allerdings mit dem Unix-Befehl grep vertraut ist, kommt auch mit den regulären Ausdrücken in Perl zurecht.

 nach obennach unten 

Reguläre Ausdrücke anwenden

Zwei kleine einführende Beispiele sollen zeigen, in welchen Situationen reguläre Ausdrücke typischerweise zum Einsatz kommen.

Beispiel eines vollständigen CGI-Scripts in Perl:

#!/usr/bin/perl -w

use strict;
use CGI::Carp qw(fatalsToBrowser);

print "Content-type: text/html\n\n";
print '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">', "\n";
print "<html><head><title>Testausgabe</title>\n";
print "</head><body>\n";

my @Orte = ("Madrid","London","Mailand","Paris","Rom","M&uuml;nchen");

foreach(@Orte) {
 if( $_ =~ /^M/ ) {
  print "$_ f&auml;ngt mit M an<br>\n";
 }
}

print "</body></html>\n";

Erläuterung:

Das Beispiel deklariert einen Seite Array namens @Orte mit sechs Städtenamen. Dann geht es die Einträge des Arrays mit einer Seite foreach-Schleife der Reihe nach durch. Im Schleifenblock wird überprüft, ob der Städtename im aktuellen Schleifendurchlauf mit M anfängt. Dazu wird die Seite vordefinierte Variablen $_, in der ja in einer foreach-Schleife der aktuelle Wert enthalten ist, mit dem Operator =~ an einen regulären Ausdruck gebunden. Der Operator =~ ist speziell für reguläre Ausdrücke gedacht. Der reguläre Ausdruck selbst steht per Voreinstellung in Schrägstrichen. Innerhalb der Schrägstriche wird ein Suchmuster definiert. Das Suchmuster ^M im Beispiel bedeutet so viel wie "fängt mit M an".
Die ganze Anweisung if( $_ =~ /^M/ ) ist also so zu lesen: wenn die Bedingung erfüllt ist, dass der Wert des aktuellen Schleifeninhalts mit einem M anfängt ...
Genaugenommen können Sie die Zeichenfolge $_ =~ auch weglassen, da der reguläre Ausdruck dann automatisch an die vordefinierte Variable $_ gebunden wird. Um eine bessere Verständlichkeit zu erhalten, wurde hier die ausführliche Notation gewählt.

Das Beispiel gibt in diesem Fall den Schleifeninhalt aus. Am Ende werden also aus dem Array @Orte die drei Städte ausgegeben, die mit M beginnen.

Das folgende Beispiel ist etwas anspruchsvoller:

Beispiel eines vollständigen CGI-Scripts in Perl:

#!/usr/bin/perl -w

use strict;
use CGI::Carp qw(fatalsToBrowser);

print "Content-type: text/html\n\n";
print '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">', "\n";
print "<html><head><title>Testausgabe</title>\n";
print "</head><body>\n";

my $Zeile = "{link:http://www.teamone.de/{TeamOne-Seiten}}";
$Zeile =~ /\{link:(.*)\{(.*)\}\}/;
my $Link = $1;
my $Linktext = $2;
print "<a href=\"$Link\">$Linktext</a>";

print "</body></html>\n";

Erläuterung:

In diesem Script gibt es einen Skalar namens $Zeile, der als Wert eine Zeichenkette speichert, die offensichtlich eine bestimmte Struktur hat. Sie steht in geschweiften Klammern. Zuerst ist link: notiert, dann folgt ein URI, und dann folgt, nochmals in geschweifte Klammern gesetzt, ein Text. Diese Struktur mit den geschweiften Klammern ist jetzt frei erfunden. Doch fast die gesamte EDV besteht daraus, Daten nach irgendwelchen für Computer wiedererkennbaren Strukturen oder Konventionen zu speichern. Reguläre Ausdrücke sind dafür geeignet, aus solchen Strukturen etwas Bestimmtes herauszufiltern. Im Beispiel filtert das Script mit Hilfe eines regulären Ausdrucks aus der Zeichenkette den URI und den Text in der zweiten, inneren geschweiften Klammer heraus und bastelt aus diesen beiden Teilwerten einen HTML-Verweis, den es am Ende mit print an den Browser ausgibt.

Mit der Anweisung $Zeile =~ /\{link:(.*)\{(.*)\}\}/; wird auf den Wert des Skalars $Zeile der reguläre Ausdruck angewendet, der zwischen den beiden Schrägstrichen steht. Um die fürchterliche Ansammlung von Zeichen erst mal etwas zu entwirren, seien zunächst die Backslashes \ darin erwähnt. Diese dienen zur Maskierung des jeweils nachfolgenden Zeichens und bedeuten einfach nur: das nächste Zeichen soll als das Zeichen behandelt werden, das da steht. Also \{ heißt beispielsweise einfach nur: das folgende Zeichen { bitte nicht anders interpretieren als es da steht.
Das, worauf der reguläre Ausdruck passen soll, soll also demnach mit der Zeichenfolge {link: anfangen. Danach kann erst mal kommen was will. Ausgedrückt wird dies durch .* Irgendwann soll dann noch mal eine öffnende geschweifte Klammer { in dem durchsuchten Wert vorkommen. Dahinter kann wieder kommen was will, also .*, und am Ende sollen noch mal zwei schließende geschweifte Klammern vorkommen. So wird also ein "Muster" mit Hilfe des regulären Ausdrucks definiert, das auf den untersuchten Wert passt, aber einige Dinge variabel lässt.
Auch hier wurde der Verständlichkeit halber eine Vereinfachung gewählt. Der Teilausdruck .* funktioniert zwar bei diesem Beispiel, kann jedoch in ungünstigen Fällen aufgrund seiner nach unten Gierigkeit zuviel erkennen.

Die beiden variablen Bereiche, also jene, die durch .* markiert sind, werden im Beispiel jeweils in runde Klammern eingeschlossen. Die runden Klammern zeigen den Wunsch an, dass Perl sich das, was zwischen diesen Klammern steht, merken soll. Im Beispiel werden sich auf diese Weise zwei variablen Bereiche gemerkt:
{link:http://www.teamone.de/{TeamOne-Seiten}}
Die fett dargestellten Bereiche sind nun in den beiden Klammern gespeichert.

Um an die gespeicherten Werte heranzukommen, stellt Perl vordefinierte Variablen namens $1, $2, $3 usw. zur Verfügung. In $1 ist der Inhalt der ersten runden Klammer im regulären Ausdruck gespeichert, in $2 der Inhalt der zweiten runden Klammer. Das Beispiel-Script deklariert zwei Skalare namens $Link und $Linktext, denen es die beiden in den runden Klammern gespeicherten Werte zuweist.

Der Rest ist dann nicht mehr schwer: in einer print-Anweisung, die den Code für einen HTML-Verweis ausgibt, werden die beiden Skalare $Link und $Linktext an den Stellen eingefügt, wo ihre Werte hingehören.

Beachten Sie:

Ein wichtiger Anwendungsbereich für reguläre Ausdrücke ist auch das nach unten Suchen und Ersetzen mit regulären Ausdrücken. Reguläre Ausdrücke können ferner in einigen Perl-Funktionen als zu übergebender Parameter vorkommen, beispielsweise in der Funktion Seite split.

 nach obennach unten 

Reguläre Ausdrücke für einzelne Zeichen

Sie können in einer Zeichenkette

Solche Ausdrücke eignen sich weniger zur Mustererkennung als dazu, um herauszufinden, ob in einem Wert bestimmte Zeichen, z.B. unerlaubte Zeichen vorkommen.

Nr. Regulärer Ausdruck (Beispiel) passt auf eine Zeichenkette, die (mindestens)
1. /a/ ein 'a' enthält
2. /[ab]/ ein 'a' oder ein 'b' enthält
3. /[A-Z]/ einen Großbuchstaben enthält (passt nicht auf Umlaute)
4. /[0-9]/ eine Ziffer enthält
5. /\d/ eine Ziffer enthält - genau wie (4.)
6. /\D/ ein Zeichen enthält, das keine Ziffer ist
7. /[-\d]/ eine Ziffer oder ein Minuszeichen enthält
8. /[\[\]]/ eine eckige Klammer enthält
9. /[a-zA-Z0-9_]/ eins der Zeichen vom Typ Buchstabe (ohne Umlaute), vom Typ Ziffer oder einen Unterstrich enthält
10. /\w/ eins der Zeichen vom Typ Buchstabe, vom Typ Ziffer oder einen Unterstrich enthält - (fast) genau wie (9.); ob Umlaute erkannt werden können, hängt von der Systemkonfiguration ab
11. /\W/ ein Zeichen enthält, was weder Buchstabe noch Ziffer noch Unterstrich ist; ob Umlaute ausgeschlossen werden können, hängt von der Systemkonfiguration ab
12. /\r/ ein Steuerzeichen für den Wagenrücklauf enthält
13. /\n/ ein Steuerzeichen für den Zeilenvorschub enthält
14. /\t/ ein Steuerzeichen für den Tabulator enthält
15. /\f/ ein Steuerzeichen für den Seitenvorschub enthält
16. /\s/ ein Leerzeichen oder ein Steuerzeichen aus (12.-15.) enthält
17. /\S/ ein Zeichen enthält, das kein Leerzeichen oder Steuerzeichen aus (12.-15.) ist
18. /[^äöüÄÖÜ]/ ein Zeichen enthält, was kein deutscher Umlaut (in der entsprechenden Zeichencodierung) ist
19. /[^a-zA-Z]/ ein Zeichen enthält, welches kein Buchstabe ist (ohne Umlaute)

Wenn Sie mit einem regulären Ausdruck prüfen wollen, ob in einer Zeichenkette ein bestimmtes Zeichen vorkommt, genügt es, dieses Zeichen innerhalb der Begrenzer (hier: der Schrägstriche) zu notieren, so wie in den Beispielen (1.) und (12.-15.). Wenn das gesuchte Zeichen innerhalb von regulären Ausdrücken ein reserviertes Zeichen ist, wie beispielsweise ein +, müssen Sie es mit einem umgekehrten Schrägstrich maskieren (\+). Reservierte Zeichen sind auf jeden Fall +?.*^$()[]{}|\.
Wenn Sie allerdings wirklich nur das Vorkommen eines festen Zeichens oder einer festen Zeichenkette überprüfen wollen, ist die Funktion Seite index die bessere Wahl.

Für reguläre Ausdrücke interessanter sind Fälle, in denen Sie prüfen wollen, ob ein Zeichen vorkommt, das auf verschiedene Möglichkeiten passen soll, oder explizit nicht passen soll, wie in den Beispielen (2.-11.) und (16.-19.). Dafür gibt es innerhalb der regulären Ausrücke die so genannten Zeichenklassen. Eine Zeichenklasse wird grundsätzlich innerhalb eckiger Klammern [...] notiert, wie in den Beispielen (2.-4.), (7.-9.) und (18.-19.). Eine Zeichenklasse passt immer genau auf ein Zeichen. Innerhalb dieser Zeichenklasse können Sie nun die verschiedenen Zeichen dieser Klasse aufzählen, indem Sie die Zeichen nacheinander notieren. Reservierte Zeichen müssen auch hierbei explizit mit einem umgekehrten Schrägstrich maskiert werden, wie in Beispiel (8.). Wenn Sie einen größeren Zeichenbereich haben, der passen soll, können Sie diesen angeben, in dem Sie das erste Zeichen des Bereichs notieren, danach ein Minuszeichen als Bindestrich - und danach das letzte Zeichen des Bereichs, wie in den Beispielen (3.), (4.), (9.) und (19.). Wenn Sie den Bindestrich als wirkliches Zeichen meinen, notieren sie ihn am Anfang der Zeichenklasse, wie in Beispiel (7.).

Für bestimmte, häufig vorkommende Zeichenklassen gibt es Abkürzungen. So entspricht [0-9] \d und [ \r\n\t\f] enspricht \s. [a-zA-Z0-9_] entspricht im allgemeinen der Abkürzung \w. Sie können diese Abkürzungen auch innerhalb von Zeichenklassen verwenden, wie in Beispiel (7.).

Sie können Zeichenklassen negieren, um festzulegen, daß sie auf ein bestimmtes Zeichen nicht passen sollen, wie in den Beispielen (18.) und (19.). Dazu notieren Sie direkt nach der öffnenden eckigen Klammer [ das Hütchensymbol ^. Beachten Sie, dass auch dann mindestens ein Zeichen in der durchsuchten Zeichenkette vorhanden sein muss, auf das der reguläre Ausdruck nicht passt, obwohl kein Buchstabe in der Zeichenkette vorkommt. Wenn Sie also Beispiel (19.) auf eine leere Zeichenkette anwenden, bekommen Sie als Ergebnis, dass der reguläre Ausdruck nicht passt. Um die abgekürzten Zeichenklassen wie etwa \s oder \d zu negieren, ändern Sie einfach den "Namen" der Abkürzung in einen Großbuchstaben, also \S oder \D.

 nach obennach unten 

Reguläre Ausdrücke für Zeichenketten

Sie können

Diese Art von regulären Ausdrücken ist dazu gedacht, um etwa in einem Wert nach dem Vorkommen eines bestimmten Wortes, einer beliebigen Teilzeichenkette oder nach einem Muster zu suchen.

Nr. Regulärer Ausdruck (Beispiel) Wirkung
1. /aus/ passt auf 'aus' - auch in 'Haus' oder 'Mausi'
2. /aus?/ passt auf 'aus' usw. - aber auch 'au' und 'auf'
3. /a./ passt auf 'ab' und 'an' (ein beliebiges Zeichen hinter 'a', außer \n)
4. /a+/ passt auf 'a' und 'aa' und 'aaaaa' (ein oder beliebig viele 'a')
5. /a*/ passt auf 'a' und 'aa' und 'aaaaa' und 'b' (kein oder beliebig viele 'a')
6. /Ha.s/ passt auf 'Haus' und 'Hans' aber nicht 'Hannes'
7. /Ha.+s/ passt auf 'Haus' und 'Hans' und 'Hannes' (ein oder beliebig viele beliebige Zeichen, außer \n)
8. /Ha.s/ passt auf 'Haus' und 'Hans' aber nicht 'Hase'
9. /Ha.?s/ passt auf 'Haus' und 'Hans' und 'Hase'
10. /x{10,20}/ passt auf zwischen 10 und 20 'x' in Folge
11. /x{10,}/ passt auf 10 und mehr 'x' in Folge
12. /x.{2}y/ passt auf 'xxxy' oder 'xaby' usw. (zwei beliebige Zeichen zwischen 'x' und 'y', außer \n)
13. /Hans\b/ passt auf 'Hans' aber nicht 'Hansel' (Wortgrenze)
14. /\baus/ passt auf 'aus' oder 'aussen' aber nicht 'Haus' (Wortgrenze)
15. /\baus\b/ passt auf 'aus' aber nicht 'Haus' und auch nicht 'aussen' (Wortgrenze)
16. /\baus\B/ passt auf 'aussen' aber nicht 'aus' und auch nicht 'Haus' (Wortgrenze und "negative" Wortgrenze)
17. /^Hans/ passt auf 'Hans' nur am Anfang des zu durchsuchenden Bereichs
18. /Hans$/ passt auf 'Hans' nur am Ende des zu durchsuchenden Bereichs
19. /^\s*$/ passt auf Zeilen, die nur aus Leerzeichen und anderen Leerraumzeichen bestehen oder leer sind
20. /$Name/ interpretiert den Inhalt des Skalars $Name als regulären Ausdruck

Wenn Sie in einem regulären Ausdruck nach einer bestimmten Zeichenkette suchen wollen, notieren Sie die Zeichenkette einfach zwischen den beiden Schrägstrichen des regulären Ausdrucks, so wie in Beispiel (1.). Allerdings gilt auch hier wie bei den nach oben regulären Ausdrücken für einzelne Zeichen: wenn Sie nach einer festen Zeichenfolge suchen, sind Sie mit der Funktion Seite index besser beraten.

Reguläre Ausdrücke sind sozusagen eine eigene Sprache, die durch Wörter, die anhand grammatischer Regeln verknüpft werden, dargestellt wird. Die Verknüpfung erfolgt durch Operatoren. Der Grund, warum reguläre Ausrücke so kompliziert erscheinen, ist die hohe Komprimierung in der Notation.

Ein Wort in der Sprache der regulären Ausdrücke wird Atom genannt. Atome stellen immer genau ein gesuchtes Zeichen dar, beispielsweise a, [abc], . oder \[. Die Zeichenklasse [abc] stellt ein Zeichen dar, das 'a', 'b' oder 'c' sein kann. Der Punkt . ist die Abkürzung für eine ganz spezielle Zeichenklasse, die alle Zeichen außer dem Zeilenumbruch beinhaltet. Er entspricht also in der DOS-Eingabeaufforderung beispielsweise dem ?. Das Konstrukt \[ stellt eine eckige Klammer dar, die aber durch den umgekehrten Schrägstrich weiter unten maskiert werden muss, wenn sie nicht als Steuerzeichen verstanden werden soll.
Um aus Atomen ein zusammenhängendes Muster zu bilden, notieren Sie die Atome einfach ohne Leerzeichen aneinander.

Zeichenwiederholungen können Sie mit Wiederholungsoperatoren kennzeichnen.
Das Fragezeichen ? bedeutet in einem regulären Ausdruck: das Zeichen vor dem Fragezeichen oder auch nicht. Siehe dazu Beispiel (2.).
Das Pluszeichen + bedeutet: eine oder mehrere Wiederholungen des Zeichens, das vor dem Pluszeichen steht. Siehe dazu Beispiel (4.).
Das Sternzeichen * bedeutet: keine, eine oder mehrere Wiederholungen des Zeichens, das vor dem Sternzeichen steht. Siehe dazu Beispiel (5.).
Wenn Sie vor den Zeichen + oder * einen Punkt notieren (der für ein beliebiges Zeichen steht, erzeugen Sie einen Platzhalter, der dem * in der DOS/Windows-Welt, etwa bei Dateinamen, entspricht. Siehe dazu Beispiele (6.) bis (9.).
Geschweifte Klammern mit einer Zahl oder zwei Zahlen n darin {n} stehen für n Wiederholungen des Zeichens vor der geschweiften Klammer an der betreffenden Stelle - siehe dazu Beispiele (10.) bis (12.). Dabei können Sie auch das Punktzeichen vor der geschweiften Klammer notieren. In diesem Fall bedeutet die Angabe innerhalb der geschweiften Klammer: so viele beliebige Zeichen wie angegeben - siehe dazu Beispiel (12.)

Sie können nach Zeichenketten suchen, die nur dann gefunden werden, wenn sie am Anfang oder am Ende eines Wortes vorkommen. Auch die Umkehrung davon ist möglich: Sie können nach Zeichenketten suchen, die nur dann gefunden werden, wenn sie nicht am Anfang oder am Ende eines Wortes vorkommen.
Mit \b vor einer Zeichenkette wird die Zeichenkette nur gefunden, wenn ein Wort damit anfängt.
Mit \b nach einer Zeichenkette wird die Zeichenkette nur gefunden, wenn ein Wort damit endet.
Mit \B vor einer Zeichenkette wird die Zeichenkette nur gefunden, wenn ein Wort nicht damit anfängt.
Mit \B nach einer Zeichenkette wird die Zeichenkette nur gefunden, wenn ein Wort nicht damit endet.
Zu diesen Möglichkeiten siehe Beispiele (13.) bis (16.).
Genau gesagt definiert \b die Grenze zwischen \w und \W (oder Zeichenkettenanfang oder -ende).

Sie können Zeichenketten suchen, die nur dann gefunden werden, wenn sie am Anfang oder am Ende einer Zeile im zu durchsuchenden Bereich vorkommen. Dies ist vor allem im Zusammenhang mit Zeilen in Textdateien interessant.
Mit dem Hütchensymbol ^ am Beginn des Suchausdrucks wird die Zeichenkette nur gefunden, wenn sie am Anfang des Bereichs steht.
Mit dem Dollarzeichen $ am Ende des Suchausdrucks wird die Zeichenkette nur gefunden, wenn sie am Ende des Bereichs steht.
Zu diesen Möglichkeiten siehe Beispiele (17.) bis (19.).

Innerhalb von regulären Ausdrücken können Sie auch Variablen verwenden. Auf diese Weise können Sie dynamische Daten als Suchmuster einsetzen. Im Zusammenhang mit CGI könnte Sie z.B. die Anwendereingabe aus einem Formularfeld in ein Suchmuster übernehmen. Siehe dazu Beispiel (20.).

 nach obennach unten 

Maskierung von Zeichen in regulären Ausdrücken

Da es bei regulären Ausdrücken einige Zeichen mit Sonderbedeutung gibt, müssen Sie solche Zeichen maskieren, wenn Sie nicht die Sonderbedeutung des Zeichens meinen, sondern seine literale, normale Bedeutung, also einen Senkrechtstrich als Senkrechtstrich oder einen Punkt als Punkt meinen. Das Maskierungszeichen ist in allen Fällen der Backslash.

Zeichen Maskierung Grund Beispiel
/ \/ Wenn der Schrägstrich den regulären Ausdruck begrenzt, muß er innerhalb davon maskiert werden. /\/usr\/bin\/perl/
. \. Der Punkt steht in regulären Ausdrücken ansonsten für ein beliebiges anderes Zeichen. /Ende aus\./
+ \+ Das Pluszeichen steht ansonsten für ein oder mehrmaliges Vorkommen des davorstehenden Zeichens. /\d\+\d/
* \* Das Sternzeichen steht ansonsten für kein, ein oder mehrmaliges Vorkommen des davorstehenden Zeichens. /\*char/
? \? Das Fragezeichen steht ansonsten für kein oder einmaliges Vorkommen des davorstehenden Zeichens. /Wie geht das\?/
^ \^ Das Dach- oder Hütchensymbol kann ansonsten eine Zeichenklasse verneinen oder bei Zeichenketten angeben, dass das nachfolgende Suchmuster am Anfang des Suchbereichs vorkommen muss. /ein \^ über dem Kopf/
$ \$ Das Dollarzeichen kann einen Skalar einleiten oder bei Zeichenketten angeben, dass das voranstehende Suchmuster am Ende des Suchbereichs vorkommen muss. /Preis (US-Dollar): \d*\$/
| \| Der Senkrechtstrich kann ansonsten alternative Ausdrücke auseinanderhalten. /find (.*) \| sort/
( ) \( \) Runde Klammern können ansonsten Teilausdrücke gruppieren und zum Merken einklammern. /\(Hinweis: (.*)\)/
[] \[ \] Eckige Klammern begrenzen ansonsten eine Zeichenklasse. /\$(.*)\[\d+\]/
{ } \{ /} Geschweifte Klammern bedeuten ansonsten eine Wiederholungsangabe für davorstehende Zeichen. /ENV\{.*\}/

 
 nach obennach unten 

Gierige und genügsame Suchmuster

Normalerweise sind alle regulären Ausdrücke, die Wildcard-Ausdrücke wie .* enthalten, sehr "gierig". Sie holen sich so viele Zeichen wie möglich. Es gibt jedoch die Möglichkeit, solche Ausdrücke zu mehr Genügsamkeit zu zwingen.

Beispiel eines vollständigen CGI-Scripts in Perl:

#!/usr/bin/perl -w

use strict;
use CGI::Carp qw(fatalsToBrowser);

print "Content-type: text/html\n\n";
print '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">', "\n";
print "<html><head><title>Testausgabe</title>\n";
print "</head><body>\n";

my $HTML_Zeile = "<html><head><title>Testausgabe</title></head><body><h1>&Uuml;berschrift</h1></body></html>";

$HTML_Zeile =~ /(^<.+>)/;
my $gierig = $1;
$HTML_Zeile =~ /(^<.+?>)/;
my $genuegsam = $1;

$gierig =~ s/</&lt;/g;    # nur wegen HTML-Ausgabe
$gierig =~ s/>/&gt;/g;    # nur wegen HTML-Ausgabe
$genuegsam =~ s/</&lt;/g; # nur wegen HTML-Ausgabe
$genuegsam =~ s/>/&gt;/g; # nur wegen HTML-Ausgabe

print "<p><b>Gierige Version:</b> <tt>$gierig</tt></p>";
print "<p><b>Gen&uuml;gsame Version:</b> <tt>$genuegsam</tt></p>";

print "</body></html>\n";

Erläuterung:

Das Beispiel-Script demonstriert die Gier regulärer Ausdrücke und zeigt auch, wie sich diese Gier unterbinden lässt. Ein Skalar namens $HTML_Zeile wird deklariert und erhält als Anfangswert den Code einer kompletten kleinen HTML-Datei. Anschließend wird dieser Skalar mit einem regulären Ausdruck bewertet, der darin nach einem Muster /(^<.+>)/ sucht. In runde Klammern eingeschlossen ist das gesamte Suchmuster, weil anschließend ausgegeben werden soll, was gefunden wurde. Das Suchergebnis wird im Skalar $gierig gespeichert. Anschließend wird die Prozedur noch mal wiederholt. Diesmal ist der reguläre Ausdruck nur minimal anders: er enthält hinter dem Pluszeichen noch ein Fragezeichen.

Beide Suchergebnisse werden anschließend noch für die HTML-Ausgabe vorbereitet, und zwar werden die spitzen Klammern HTML-gerecht ersetzt (siehe dazu auch nach unten Suchen und Ersetzen mit regulären Ausdrücken).

Die Ausgabe von $gierig bewirkt:
<html><head><title>Testausgabe</title></head><body><h1>Überschrift</h1></body></html>
Die Ausgabe von $genuegsam dagegen:
<html>

Der Wildcard-Ausdruck .+, der "alles" bis zum Zeichen > holen soll, macht nämlich nicht beim nächsten > Stopp, sondern erst beim allerletzten. Durch das Anhängen des Fragezeichens, also durch Erweiterung auf .+?, beschränkt sich das Muster auf das Auffinden des nächsten >-Zeichens.

 nach obennach unten 

Reguläre Ausdrücke mit Alternativen

Sie können mehrere Suchausdrücke angeben. Dann passt der Ausdruck auf alle Zeichenketten, in denen wenigstens eine der Alternativen vorkommt.

Beispiel eines vollständigen CGI-Scripts in Perl:

#!/usr/bin/perl -w

use strict;
use CGI::Carp qw(fatalsToBrowser);

print "Content-type: text/html\n\n";
print '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">', "\n";
print "<html><head><title>Testausgabe</title>\n";
print "</head><body>\n";

my $Text = "Kaffee ohne Milch";
print "egal ob mit oder ohne<br>\n" if ($Text =~ /mit|ohne/);
$Text = "Kaffee mit Milch";
print "sag ich doch: egal ob mit oder ohne<br>\n" if ($Text =~ /mit|ohne/);

print "</body></html>\n";

Erläuterung:

Das Beispiel-Script deklariert einen Skalar $Text mit dem Anfangswert Kaffee ohne Milch. Abhängig vom Erfolg des regulären Ausdrucks /mit|ohne/, der auf diesen Skalar angewendet wird, wird im aufrufenden Browser ausgegeben: egal ob mit oder ohne. Der Senkrechtstrich | teilt den regulären Ausdruck auf in zwei Alternativen, bei denen es reicht, wenn eine davon zutrifft. Da dies der Fall ist, wird der Satz im Browser ausgegeben. Zur Kontrolle wird der Text anschließend zu Kaffee mit Milch geändert. Der anschleßend angewendete gleiche reguläre Ausdruck führt wieder zum Erfolg, und es wird sag ich doch: egal ob mit oder ohne ausgegeben.

 nach obennach unten 

Teilausdrücke merken mit Klammerung

Mit Hilfe von Klammerung einzelner Teile eines regulären Ausdrucks können Sie Teilmuster speichern und an einer späteren Stelle wiederverwenden.

Beispiel eines vollständigen CGI-Scripts in Perl:

#!/usr/bin/perl -w

use strict;
use CGI::Carp qw(fatalsToBrowser);

print "Content-type: text/html\n\n";
print '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">', "\n";
print "<html><head><title>Testausgabe</title>\n";
print "</head><body>\n";

my $CTIME = localtime(time);
$CTIME =~ /^([A-Za-z]*?)\s*([A-Za-z]*?)\s*(\d*?)\s*(\d*?):(\d*?):(\d*)\s*(\d*)$/;
my $Tag = $1;
my $Monat = $2;
my $Monatstag = $3;
my $Stunden = $4;
my $Minuten = $5;
my $Sekunden = $6;
my $Jahr = $7;
my %Tage   = (Mon => "Montag", Tue => "Dienstag", Wed => "Mittwoch",
              Thu => "Donnerstag", Fri => "Freitag", Sat => "Samstag", Sun => "Sonntag");
my %Monate = (Jan => "01", Feb => "02", Mar => "03", Apr => "04", May => "05", Jun => "06",
              Jul => "07", Aug => "08", Sep => "09", Oct => "10", Nov => "11", Dec => "12");

print "<b>Heute ist $Tage{$Tag}, der $Monatstag.$Monate{$Monat}.$Jahr, es ist $Stunden.$Minuten Uhr</b>\n";

print "</body></html>\n";

Erläuterung:

Das Beispiel ruft die Perl-Funktion Seite localtime mit dem Rückgabewert der Funktion Seite time auf und speichert den Rückgabewert von localtime im Skalar $CTIME. Darin ist anschließend eine Zeichenkette gespeichert, die so aufgebaut ist:
Sun Jun 17 21:37:40 2001

In der darauffolgenden Anweisung wird $CTIME mit einem langen regulären Suchausdruck bewertet. Der reguläre Ausdruck versucht, das gesamte typische Muster des Datum-Uhrzeit-Strings zu erfassen. Die Nutzdaten darin, also Wochentag, Monatsname, Monatstag, Stunden, Minuten, Sekunden und Jahr werden innerhalb des regulären Ausdrucks geklammert. Jeden Inhalt dieser Klammern merkt sich Perl und stellt ihn in den Seite vordefinierten Variablen $1, $2, $3 usw. zur Verfügung. Die anschließend deklarierten Skalare holen sich die Werte aus den Klammern, indem ihnen die entsprechenden vordefinierten Variablen zugewiesen werden.

Die beiden Hashes %Tage und %Monate werden zum Zweck eines deutschsprachigen Datum-Uhrzeit-Formats verwendet. Das Script gibt am Ende so etwas aus wie:
Heute ist Sonntag, der 17.06.2001, es ist 21.37 Uhr.

 nach obennach unten 

Rangfolge in regulären Ausdrücken

Die Sonderzeichen innerhalb von regulären Ausdrücken werden vom Perl-Interpreter nach einer bestimmten Rangfolge bewertet.

  1. Rangstufe: () (Klammerung)
  2. Rangstufe: + * ? {#,#} (Wiederholungsoperatoren)
  3. Rangstufe: abc ^ $ \b \B (Zeichen/Zeichenketten, Zeilenanfang/-ende, Wortanfang/-ende)
  4. Rangstufe: | (Alternativen)

Dadurch ist jeder reguläre Ausdruck eindeutig bewertbar. Wenn Sie in einem Ausdruck jedoch anders bewerten möchten, als es nach der Rangfolge geschieht, können Sie innerhalb des Ausdrucks Klammern setzen, um eine andere Bewertung zu erzwingen.

Beispiele:

/a|bc|d/       # findet 'a' oder 'bc' oder 'd'
/(a|b)(c|d)/   # findet 'ac' oder 'ad' oder 'bc' oder 'bd'

Erläuterung:

Laut der Rangfolge haben Zeichen bzw. Zeichenketten Vorrang vor dem Trennzeichen für Alternativen. Mit Hilfe von Klammern können Sie eine andere Bewertung erzwingen (siehe Beispiel).
Wenn Sie die Klammern zur Bewertungsänderung benutzen möchten, ohne sich die entsprechenden nach oben Teilausdrücke merken zu wollen, können Sie auch Klammern benutzen, die nur gruppieren. Dabei wird direkt hinter der öffnenden Klammer die Zeichenfolge ?: notiert, im Beispiel wäre das (?:a|b)(?:c|d).

 nach obennach unten 

Flags hinter regulären Ausdrücken

Hinter dem beendenden Begrenzerzeichen (normalerweise: Schrägstrich) eines regulären Ausdrucks können noch ein oder mehrere Buchstaben notiert werden - so genannte Flags. Damit können Sie das Verhalten der Suche zusätzlich beeinflussen. Mit einer Notation wie /aus/g suchen Sie beispielsweise global nach dem Vorkommen von aus, und mit /aus/gim suchen Sie die Zeichenfolge aus global, egal ob groß oder klein geschrieben, und die Zeichenkette kann auch aus mehreren Zeilen bestehen. Flags können Sie also beliebig kombinieren. Die folgende Tabelle listet die möglichen Flags auf.

Flag Bedeutung
c Bei einem auftretenden Fehler nicht die Suchposition zurücksetzen.
g Global suchen, d.h. alle Vorkommen finden.
i Groß-/Kleinschreibung ignorieren
m Zeichenketten können aus mehreren Zeilen bestehen
o Suchmuster nur einmal anwenden
s Zeichenketten als eine einzige Zeile betrachten
x Erweiterte Syntax verwenden

 

 nach obennach unten 

Suchen und Ersetzen mit regulären Ausdrücken

Reguläre Ausdrücke sind das Mittel, mit dem in Perl in Zeichenketten etwas gesucht und ersetzt wird.

Beispiel 1 eines vollständigen CGI-Scripts in Perl:

#!/usr/bin/perl -w

use strict;
use CGI::Carp qw(fatalsToBrowser);

print "Content-type: text/plain\n\n";

my $Text = "Franz jagt im komplett verwahrlosten Taxi quer durch Bayern 1234567890";
$Text =~ s/[a-z]| //gi;

print "$Text\n";

Erläuterung:

Das Schema für alle Suche-Ersetze-Vorgänge in Perl lautet:
$Zeichenkette =~ s/Suchmuster/Ersatzzeichenkette/[Flags]

$Zeichenkette ist ein Skalar, in dem eine Zeichenkette gespeichert ist, so wie etwa $Text im obigen Beispiel 1. Dieser Skalar wird mit dem Operator =~ an die Ersetzung gebunden, d.h. der Suche-Ersetze-Vorgang gilt für den Inhalt des Skalars. Dahinter notieren Sie die Ersetzung. Sie wird durch ein kleines s eingeleitet. Nach dem s notieren Sie das erste Begrenzerzeichen (per Voreinstellung ein Schrägstrich), und danach das Suchmuster, das mit dem zweiten Begrenzerzeichen abgeschlossen wird. Danach folgen das Zeichen oder die Zeichenfolge, durch die Fundstellen ersetzt werden sollen, die mit dem dritten Begrenzerzeichen abgeschlossen werden. Falls benötigt notieren Sie nach dem letzten Begrenzerzeichen noch Flags für den Such-Ersetze-Vorgang. Im Beispiel wurden folgende Flags verwendet:
g sucht/ersetzt alle Fundstellen (ansonsten wird nur die erste Fundstelle ersetzt)
i sucht/ersetzt Buchstaben unabhängig davon, ob sie groß oder klein geschrieben sind (ansonsten wird Groß-/Kleinschreibung unterschieden).

Im obigen Beispiel werden aus dem Skalar $Text alle Buchstaben (groß und klein) und alle Leerzeichen entfernt. Es bleiben anschließend also nur noch die Ziffern am Ende stehen. Das Ergebnis wird zur Kontrolle ausgegeben.

Beispiel 2 eines vollständigen CGI-Scripts in Perl:

#!/usr/bin/perl -w

use strict;
use CGI::Carp qw(fatalsToBrowser);

print "Content-type: text/plain\n\n";

my $Text = "In München steht ein Hofbräuhaus, dort gibt es Bier in Maßen";
$Text =~ s/ä/&auml;/g;
$Text =~ s/ö/&ouml;/g;
$Text =~ s/ü/&uuml;/g;
$Text =~ s/Ä/&Auml;/g;
$Text =~ s/Ö/&Ouml;/g;
$Text =~ s/Ü/&Uuml;/g;
$Text =~ s/ß/&szlig;/g;

print "$Text\n";

Erläuterung:

Im diesem Beispiel werden in $Text alle deutschen Umlaute und scharfes S durch ihre HTML-gerechten Umschreibungen ersetzt. Das Ergebnis wird zur Kontrolle ausgegeben.

 nach obennach unten 

Transliteration

Für "kleinere" Aufgaben wie Suchen und Ersetzen oder das Zählen von einzelnen Zeichen gibt es in Perl die Möglichkeit, ohne reguläre Ausdrücke zu arbeiten. Dafür gibt es eine spezielle Syntax, den Transliterationsoperator tr.

Beispiel eines vollständigen CGI-Scripts in Perl:

#!/usr/bin/perl -w

use strict;
use CGI::Carp qw(fatalsToBrowser);

print "Content-type: text/plain\n\n";

my $Prinzip = "abc";
$Prinzip =~ tr/ac/xy/;
print "Prinzip = $Prinzip\n";

my $chinesisch = "chinesisches Roulette rigoros";
$chinesisch =~ tr/Rr/Ll/;
print "chinesisch = $chinesisch\n";

my $Geschrei = "WIE GEHT DAS ALLES MIT PERL?";
$Geschrei =~ tr/A-Z/a-z/;
print "Geschrei = $Geschrei\n";

my $Variablenname = "Sügümälüxümülä";
$Variablenname =~ tr/A-Za-z_0-9/_/c;
print "Variablenname = $Variablenname\n";

my $unsauber = "ein   Satz mit  überflüssigen    Leerzeichen";
$unsauber =~ tr/ //s;
print "unsauber = $unsauber\n";

my $WSatz = "Wir Westerwälder Waschweiber wollen weiße Wäsche waschen";
my $WZaehler = ($WSatz =~ tr/Ww//);
print "W/w kommt in WSatz $WZaehler mal vor!\n";

my $AchtBitWort = "überschüssig";
$AchtBitWort =~ tr/\200-\377/\000-\177/;
print "AchtBitWort = $AchtBitWort\n";

my $ROT13_Satz = "ihr seid ja solche Deppen da!";
$ROT13_Satz =~ tr/a-zA-Z/n-za-mN-ZA-M/;
print "ROT13_Satz = $ROT13_Satz\n";

Erläuterung:

Eine Transliteration besteht darin, einzelne Zeichen durch andere Zeichen zu ersetzen. Das Schema für eine Transliteration in Perl lautet:
$Zeichenkette =~ tr/Suchmuster/Ersetzmuster/[Optionen]
Dabei sind sowohl das Suchmuster als auch das Ersetzmuster keine Zeichenketten, sondern nur einzelne Zeichen oder Zeichenbereiche. Die Muster sind sozusagen zwei Listen von Zeichen. Wenn in $Zeichenkette ein Zeichen gefunden wird, das in der Suchliste vorkommt, wird es mit dem Zeichen ersetzt, das an derselben Position in der Ersetzungsliste steht.

Alle Beispiele des obigen Scripts sind gleich aufgebaut. Es wird ein Skalar mit einem "interessanten" Wert deklariert. Dann wird eine Transliteration auf diesen Wert angewendet, und anschließend wird das Ergebnis ausgegeben.

Im Fall von $Prinzip wird das Prinzip der Transliteration deutlich: in dem Beispiel wird a durch x ersetzt und c durch y. Die Ausgabe lautet daher:
Prinzip = xby

Im Fall von $chinesisch werden die Buchstaben R und r durch L und l ersetzt. Die Ausgabe lautet daher:
chinesisch = chinesisches Loulette ligolos

Im Fall von $Geschrei werden alle Großbuchstaben durch entsprechende Kleinbuchstaben ersetzt (entspricht etwa der Funktion Seite lc). Die Ausgabe lautet daher:
Geschrei = wie geht das alles mit perl?

Im Fall von $Variablenname werden alle Zeichen, die kein Buchstabe von A bis Z oder a bis z oder eine Ziffer oder ein Unterstrich sind, durch den Unterstrich _ ersetzt. Die Ausgabe lautet daher:
Variablenname = S_g_m_l_x_m_l_

Im Fall von $unsauber werden alle doppelten oder mehrfachen Leerzeichen entfernt. Die Ausgabe lautet daher:
unsauber = ein Satz mit überflüssigen Leerzeichen

Im Fall von $WSatz wird sich der Rückgabewert einer Transliteration zueigen gemacht. Dem Skalar $WSatz passiert dabei nichts weiter, aber der Rückgabewert ermittelt, wie oft die Buchstaben W oder w in dem Satz vorkommen. Die Ausgabe lautet daher:
W/w kommt in WSatz 9 mal vor!

Im Fall von $AchtBitWort werden alle Zeichen mit Zeichenwerten zwischen 128 und 255 in Zeichen mit entsprechenden Zeichenwerte zwischen 0 und 127 umgewandelt. Die Ausgabe lautet daher:
AchtBitWort = |berfl|ssig

Im Fall von $ROT13_Satz werden alle Zeichen des ersten Alphabethälfte in solche der zweiten verwandelt und umgekehrt (sie werden sozusagen um 13 Zeichenwerte rotiert). Die Ausgabe lautet:
ROT13_Satz = vue frvq wn fbypur Qrccra qn!
(das ROT13-Prinzip wird in den Newsgroups manchmal angewendet, um Dinge zu sagen, die nicht jeder verstehen können soll).

 nach oben
weiter Seite Subroutinen
zurück Seite Operatoren
 

© 2001 E-Mail selfhtml@teamone.de