Perl/Reguläre Ausdrücke

Aus SELFHTML-Wiki
Wechseln zu: Navigation, Suche

Reguläre Ausdrücke (oder kurz: Regexps von engl. regular expressions) stellen in der Programmierung verallgemeinerte Suchmuster dar. Mithilfe dieser Suchmuster können Sie beispielsweise Variableninhalte durchsuchen und bestimmte Inhalte daraus herausziehen oder ersetzen. So können Sie mit 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 Browser übertragen lassen. Reguläre Ausdrücke sind auch ein mächtiges Mittel, um große Datenbestände nach komplexen Suchausdrücken zu durchforsten. Beispielsweise könnten alle Begriffe gesammelt werden, die mit „A“ beginnen und auf „tion“ oder „tung“ enden, was mit gewöhnlichen Stringfunktionen nur mühselig zu bewerkstelligen wäre. Der Webcomic xkcd liefert ein eindrucksvolles und motivierendes Beispiel für diese vielzitierte Mächtigkeit der regulären Ausdrücke, siehe xkcd #208.

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 Scripts ziemlich merkwürdige, kryptisch anmutende Zeichenfolgen vorkommen. Wer allerdings mit Unix-Befehlen wie grep oder sed vertraut ist, kommt auch schnell mit den regulären Ausdrücken in Perl, Python, Javascript, PHP etc. zurecht, da sich die Regexp-Implementierungen (auch Regexp-Engines genannt) ähneln.

Inhaltsverzeichnis

[Bearbeiten] Einführende Beispiele

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

[Bearbeiten] Einfaches Beispiel

Beispiel
#!/usr/bin/perl
use strict;
use warnings;
 
my @Orte = ("Madrid","London","Mailand","Paris","Rom","München");
 
foreach(@Orte){
  if($_ =~ /^M/){
    print "$_ fängt mit M an\n";
  }
}
Das Beispiel deklariert ein Array namens @Orte mit sechs Städtenamen. Dann geht es die Einträge des Arrays mit einer 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 vordefinierte Variable $_, in der in einer foreach-Schleife der aktuelle Wert enthalten ist, mit dem Operator =~ an einen regulären Ausdruck gebunden. Der Operator =~ ist in Perl speziell für reguläre Ausdrücke gedacht. Der reguläre Ausdruck selbst steht per Voreinstellung in Slashes. Innerhalb der Slashes wird ein Suchmuster definiert. Das Suchmuster ^M im Beispiel bedeutet soviel 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 ...

Genau genommen können Sie die Zeichenfolge $_ =~ auch weglassen, da der reguläre Ausdruck dann automatisch an die vordefinierte Variable $_ gebunden wird. Später in diesem Abschnitt wird erklärt, dass sogar die Schleife nicht explizit notiert werden muss. 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.

[Bearbeiten] Anspruchsvolleres Beispiel

Beispiel
#!/usr/bin/perl
 
use strict;
use warnings;
use CGI;
use CGI::Carp qw(fatalsToBrowser);
 
my $cgi = new CGI;
print $cgi->header(), $cgi->start_html();
 
my $Zeile = "{link:http://de.selfhtml.org/{SELFHTML-Seiten}}";
$Zeile =~ /\{link:(.*)\{(.*)\}\}/;
my $Link = $1;
my $Linktext = $2;
print "<a href=\"$Link\">$Linktext</a>";
 
print $cgi->end_html;
In diesem Script gibt es eine Variable namens $Zeile, die als Wert eine Zeichenkette speichert, welche eine bestimmte Struktur hat. Die Zeichenkette steht in geschweiften Klammern. Zuerst ist link: notiert, dann folgt ein URI und dann folgt, nochmals in geschweiften 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 mithilfe 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 ausgibt.

Mit der Anweisung $Zeile =~ /\{link:(.*)\{(.*)\}\}/; wird der reguläre Ausdruck, der zwischen den beiden Slashes steht, auf den Wert der Variable $Zeile angewendet. Um die fürchterliche Ansammlung von Zeichen erst einmal etwas zu entwirren, seien zunächst die Backslashes \ darin erwähnt. Diese dienen zur Maskierung des jeweils nachfolgenden Zeichens und bedeuten, dass es literal gemeint ist, das heißt 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 einmal eine öffnende geschweifte Klammer { in dem durchsuchten Wert vorkommen. Dahinter kann wieder kommen was will, also .*, und am Ende sollen nochmals zwei schließende geschweifte Klammern vorkommen. So wird also ein "Muster" mithilfe 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 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 merkt es sich auf diese Weise zwei variable Bereiche:

{link:http://www.selfhtml.org/{SELFHTML-Seiten}}

Die fett dargestellten Bereiche sind nun in den beiden runden Klammern gespeichert.

Um an die gespeicherten Werte heranzukommen, stellt Perl die vordefinierte Variablen $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 Variablen 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 Variablen $Link und $Linktext an den Stellen eingefügt, wo ihre Werte hingehören.

[Bearbeiten] Begrifflichkeiten

Durch reguläre Ausdrücke, deren Ursprung in der theoretischen Informatik im Bereich der formalen Sprachen angesiedelt ist, können regelrechte Grammatiken definiert und damit Sprachen konstruiert werden. An dieser Stelle sei auf den Wikipedia-Artikel über reguläre Ausdrücke verwiesen, der diesen Hintergrund näher beleuchtet. Ein Grund, warum reguläre Ausdrücke so kompliziert erscheinen, ist die hohe Komprimierung in der Notation.

Wie in vielen Bereichen der Informatik werden auch bei den regulären Ausdrücken gerne einige englische Fachbegriffe (teilweise eingedeutscht) übernommen, was es zudem erleichtert, englischsprachige Dokumentationen zu verstehen. Bei den regulären Ausdrücken taucht beispielsweise immer wieder der praktische Begriff matchen auf, der sich je nach Kontext mit auf etwas passen oder finden übersetzen lässt. Ein regulärer Ausdruck wird auch als Pattern (Muster) bezeichnet; Teile davon als Subpattern. So matcht also das Pattern /Gras.*rosa/ beim String 'Das Gras ist nicht rosa!' den Teilstring 'Gras ist nicht rosa'. Dabei matcht das Subpattern .* den Teilstring 'ist nicht'.

[Bearbeiten] Reguläre Ausdrücke für einzelne Zeichen

Sie können in einer Zeichenkette

  • nach einem bestimmten Zeichen suchen,
  • nach einem Zeichen aus einer bestimmten Zeichenklasse suchen.

Solche Ausdrücke eignen sich weniger zur Mustererkennung als dazu, herauszufinden, ob in einer Zeichenkette bestimmte, z.B. unerlaubte Zeichen vorkommen. Die Pattern in den folgenden beiden Tabellen matchen also jeweils immer nur maximal ein Zeichen, unabhängig davon wie lang der zu durchsuchende String ist. In der ersten Tabelle werden jeweils Ausdrücke für feste Zeichen angegeben. Die zweite Tabelle gibt Beispiele für Zeichenklassen an.

Tabelle - Zeichenbeispiele für reguläre Ausdrücke
Nr. Regulärer Ausdruck passt auf eine Zeichenkette, die (mindestens)
1. /a/ ein 'a' enthält
2. /\x61/ ein 'a' enthält – genau wie Beispiel (1.), allerdings in hexadezimaler Regexp-Notation
3. /\x{20AC}/ ein Euro-Symbol '' enthält, ebenfalls in hexadezimaler Notation
4. /\N{EURO SIGN}/ ein Euro-Symbol '€' enthält, wobei die Unicode-Bezeichnung verwendet wird
5. /\077/ ein Fragezeichen enthält, in oktaler Notation
6. /\r/ ein Steuerzeichen für den Wagenrücklauf (carriage return) enthält
7. /\n/ ein Steuerzeichen für den Zeilenvorschub (line feed) enthält
8. /\t/ ein Steuerzeichen für den Tabulator enthält
9. /\f/ ein Steuerzeichen für den Seitenvorschub enthält
10. /\cK/ ein Steuerzeichen enthält, das mit Control+K erzeugt wird
11. /\e/ ein Escape-Zeichen enthält
12. /\a/ ein Steuerzeichen Bell (Glocke) enthält

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: Slashes) zu notieren, so wie in den Beispielen (1.-12.). Wenn das gesuchte Zeichen innerhalb von regulären Ausdrücken ein reserviertes Meta-Zeichen (engl. meta character) ist wie beispielsweise ein +, müssen Sie es normalerweise mit einem Backslash maskieren (\+). Meta-Zeichen sind auf jeden Fall +?.*^$()[]{}|\. Genaueres wird im Abschnitt Maskierung von Zeichen in regulären Ausdrücken erklärt.

Sie können jedes Zeichen auch über seinen Hexadezimalwert mit \xnn bzw. \x{nnnn} oder seinen Oktalwert mit \0nn eingeben wie in den Beispielen (2.-3.) bzw. (5.). Es ist auch möglich, Zeichen aus dem riesigen Unicode-Zeichenvorrat zu matchen, wie die Beispiele (2.-4.) verdeutlichen. Für häufig verwendete Steuerzeichen bieten darüber hinaus einige Regexp-Engines die in den Beispielen (6.-12.) angegebenen Abkürzungen.

Hinweis
Wenn Sie allerdings wirklich nur das Vorkommen eines festen Zeichens oder einer festen Zeichenkette überprüfen wollen, sind meistens die gewöhnlichen Stringfunktionen die effizientere Wahl.

Für reguläre Ausdrücke interessanter sind Fälle, in denen Sie prüfen wollen, ob ein Zeichen einer Auswahl von verschiedenen Zeichen vorkommt, wie in den Beispielen (13.-31.). Dafür gibt es innerhalb der regulären Ausdrücke die sogenannten Zeichenklassen, die nun in der zweiten Tabelle beispielhaft präsentiert werden.

Tabelle - Zeichenklassenbeispiele für reguläre Ausdrücke
Nr. Regulärer Ausdruck passt auf eine Zeichenkette, die (mindestens)
13. /[ab]/ ein 'a' oder ein 'b' enthält
14. /[A-Z]/ einen Großbuchstaben enthält (passt nicht auf Umlaute)
15. /[0-9]/ eine Ziffer enthält
16. /\d/ eine Ziffer enthält - genau wie Beispiel (15.)
17. /\D/ ein Zeichen enthält, das keine Ziffer ist
18. /[-\d]/ eine Ziffer oder ein Minuszeichen enthält
19. /[[\]]/ eine eckige Klammer enthält (die schließende Klammer muss maskiert werden.)
20. /[a-zA-Z0-9_]/ ein Zeichen vom Typ Buchstabe (ohne Umlaute), vom Typ Ziffer oder einen Unterstrich enthält
21. /\w/ ein Zeichen vom Typ Buchstabe, vom Typ Ziffer oder einen Unterstrich enthält - (fast) genau wie Beispiel (10.); ob Umlaute erkannt werden können, hängt von der Systemkonfiguration ab
22. /\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
23. /\s/ ein Leerzeichen oder ein Steuerzeichen aus Beispielen (6.-9.), also whitespace, enthält
24. /\S/ ein Zeichen enthält, das kein Leerzeichen oder Steuerzeichen aus Beispielen (6.-9.) ist
25. /[^äöüÄÖÜ]/ ein Zeichen enthält, was kein deutscher Umlaut (in der entsprechenden Zeichenkodierung) ist
26. /[^a-zA-Z]/ ein Zeichen enthält, welches kein Buchstabe ist (ohne Umlaute)
27. /[a-ZA-Z[:digit:]_]/ ein Zeichen vom Typ Buchstabe (ohne Umlaute), vom Typ Ziffer oder einen Unterstrich enthält, genau wie Beispiel (20.), allerdings mit POSIX-Notation für Ziffern
28. /[[:^digit:]]/ ein Zeichen enthält, das keine Ziffer ist - genau wie Beispiel (19.), allerdings in POSIX-Notation
29. /\p{IsDigit}/ eine Ziffer enthält - genau wie Beispiel (15.), allerdings in Unicode-Notation
30. /\p{Devanagari}/ ein Zeichen der indischen Schrift Devanagari enthält
31. /./ ein beliebiges Zeichen, das kein Zeilenumbruch ist

Eine Zeichenklasse wird meist innerhalb eckiger Klammern [...] notiert, wie in den Beispielen (13.-15., 18.-20. und 25.-28.). Eine Zeichenklasse matcht immer genau ein Zeichen. Innerhalb dieser Zeichenklasse können Sie nun die verschiedenen Zeichen dieser Klasse aufzählen, indem Sie die Zeichen nacheinander notieren. Einige reservierte Meta-Zeichen müssen auch hierbei explizit mit einem Backslash maskiert werden wie in Beispiel (19.). Diese Zeichen sind -]\^/$ (die öffnende eckige Klammer muss also nicht maskiert werden; genaueres siehe Abschnitt Maskierung von Zeichen in regulären Ausdrücken). Wenn Sie einen größeren Zeichenbereich haben, der passen soll, können Sie diesen angeben, indem Sie das erste Zeichen des Bereichs notieren, danach ein gewöhnliches Bindestrichminuszeichen als Bis-Strich - und danach das letzte Zeichen des Bereichs, wie in den Beispielen (14., 15., 20. und 26.). Wenn Sie den Bindestrich literal, also als wirkliches Zeichen meinen, notieren Sie ihn am Anfang oder am Ende der Zeichenklasse, wie in Beispiel (18.). Alternativ kann seine Meta-Bedeutung auch durch Maskierung mittels Backslash aufgehoben werden oder wenn er unmittelbar vor oder nach einer abgekürzten Zeichenklasse \w, \W, \s, \S, \d oder \D steht.

Für bestimmte häufig vorkommende Zeichenklassen gibt es Abkürzungen. So entspricht [0-9] dem kürzeren \d und [ \r\n\t\f] entspricht \s. Die Zeichenklasse [a-zA-Z0-9_] entspricht im Allgemeinen der Abkürzung \w, wobei \w je nach Einstellungen auch Umlaute, das Eszett oder andere regionale Schriftzeichen enthält. Sie können diese Abkürzungen auch innerhalb von Zeichenklassen verwenden, wie in Beispiel (18.). Mit dem Punkt ., wie er in Beispiel (31.) benutzt wird, existiert ein Platzhalter für ein beliebiges Zeichen (außer Zeilenumbrüchen). Bei Definitionen von Zeichenklassen, also innerhalb von eckigen Klammern [] hat der Punkt jedoch seine literale Bedeutung.

Sie können wie in den Beispielen (25. und 26.) Zeichenklassen negieren, um festzulegen, dass jene ein Zeichen matchen sollen, dass keinem der angegebenen Zeichen entspricht. Dazu notieren Sie direkt nach der öffnenden eckigen Klammer [ das Hütchensymbol ^. Beachten Sie, dass für einen erfolgreichen Match dann mindestens ein Zeichen in der durchsuchten Zeichenkette vorhanden sein muss, auf das der reguläre Ausdruck nicht passt. Wenn Sie also Beispiel (26.) auf eine leere Zeichenkette anwenden, bekommen Sie als Ergebnis, dass der reguläre Ausdruck nicht passt, obwohl kein Buchstabe der Zeichenkette vorkommt. Um abgekürzte Zeichenklassen wie etwa \s oder \d zu negieren, ändern Sie einfach den "Namen" der Abkürzung in einen Großbuchstaben, also \S bzw. \D.

Für Zeichenklassen existiert auch eine POSIX-Norm. Dazu wird innerhalb der Zeichenklassen [:class:] notiert wie in den Beispielen (27.-28.). class kann dabei eine der Klassen alpha, alnum, ascii, blank, cntrl, digit, graph, lower, print, punct, space, upper, word, xdigit sein. Die genauen Bedeutungen dieser Zeichenklassen können Sie im Abschnitt perlre im Perl-Manual nachlesen.

Die Beispiele (29.-30.) demonstrieren, dass Perl Ihnen mittels \p{} sogar die Möglichkeit bietet, nach Zeichen bestimmter vordefinierter Unicode-Zeichenklassen zu suchen. Da es den Rahmen sprengen würde, hier alle diese Möglichkeiten aufzulisten, sei an dieser Stelle auf die Übersicht des Abschnitts perlunicode im Perl-Manual verwiesen.

[Bearbeiten] Reguläre Ausdrücke für Zeichenketten

Sie können nach einer bestimmten Zeichenkette suchen und dabei verschiedene Vorgaben an die zu suchende Zeichenkette oder deren Umgebung vorgeben. Die im vorigen Abschnitt behandelten Ausdrücke, mit denen einzelne Zeichen gematcht werden, können kombiniert werden, um ganze Zeichenfolgen zu matchen. Dies ist dazu gedacht, um etwa in einer Variable nach dem Vorkommen einer beliebigen Teilzeichenkette oder allgemein nach einem Muster zu suchen.

Die nachfolgende Tabelle gibt einen ersten Überblick über einige häufig verwendete Ausdrücke.

Tabelle - Beispiele für einfache reguläre Ausdrücke durch Kombination von Symbolen für einzelne Zeichen
Nr. Regulärer Ausdruck Wirkung
1. /aus/ matcht 'aus' - auch in 'Haus' oder 'Mausi'
2. /a./ matcht 'ab' und 'an' (ein beliebiges Zeichen hinter 'a', außer \n)
3. /a[ul]s/ matcht 'aus' oder 'als' - auch in 'Haus', 'Mausi', 'Gralsuche' oder 'also'
4. /Ha.s/ matcht 'Haus' und 'Hans', aber keinen Teilstring von 'Hannes'
5. /Hans\b/ matcht 'Hans', aber nicht in 'Hansel' (Wortgrenze)
6. /\baus/ matcht 'aus' in 'auskratzen', aber nicht in 'Haus' (Wortgrenze)
7. /\baus\b/ matcht 'aus', aber nicht in 'Haus' und auch nicht 'auskratzen' (Wortgrenze)
8. /\baus\B/ matcht 'aus' in 'auskratzen', aber nicht in 'aus' und auch nicht in 'Haus' (Wortgrenze und Nicht-Wortgrenze)
9. /^Hans/ matcht 'Hans' nur am Anfang des zu durchsuchenden Bereichs, also z.B. nicht in 'Der Hans'.
10. /Hans$/ matcht 'Hans' nur am Ende des zu durchsuchenden Bereichs, wobei ein Newline-Zeichen noch Folgen darf.
11. /$Name/ interpretiert den Inhalt der Variable $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 Slashes des regulären Ausdrucks, so wie in Beispiel (1.). Allerdings gilt auch hier wie bei den regulären Ausdrücken für einzelne Zeichen: wenn Sie nach einer festen Zeichenfolge suchen, sind Sie mit den gewöhnlichen Stringfunktionen wie z.B. in Perl der Funktion index besser beraten.

Die Beispiele (1.-4.) zeigen, dass die im vorigen Abschnitt behandelten einzelnen Zeichen bzw. Zeichenklassen durch einfache Aneinanderkettung zu Ausdrücken für Zeichenketten werden. Beachten Sie, dass es diesen vier Beispielen schon genügt, wenn Teilzeichenketten dem jeweils vorgegebenen Muster entsprechen. Sie können jedoch auch 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 (word boundary - Wortgrenze) vor einer Zeichenkette wird die Zeichenkette nur gematcht, wenn ein Wort damit anfängt.
Mit \b nach einer Zeichenkette wird die Zeichenkette nur gematcht, 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 (5.-8.). Genau gesagt definiert \b die Grenze zwischen \w und \W (bzw. zwischen \w und Zeichenkettenanfang oder -ende).

Sie können auch Zeichenketten suchen, die nur dann gematcht werden, wenn sie am Anfang oder am Ende einer Zeile des zu durchsuchenden Bereichs vorkommen. Mit dem Zirkumflex ^ 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 gematcht, wenn sie am Ende des Bereichs steht, wobei noch ein Zeilenumbruch folgen darf.

Zu diesen Möglichkeiten siehe Beispiele (9.) und (10.). Detaillierter wird auf diese Anchors im Abschnitt über die Modifiers eingegangen.

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önnen Sie z.B. die Anwendereingabe aus einem Formularfeld in ein Suchmuster übernehmen. Siehe dazu Beispiel (11.).

[Bearbeiten] Maskierung von Zeichen in regulären Ausdrücken

Da es bei regulären Ausdrücken einige Meta-Zeichen (engl. Metacharacters) mit Sonderbedeutung gibt, müssen Sie solche Zeichen maskieren (auch escapen oder engl. quote), wenn Sie nicht die Meta-Bedeutung des Zeichens meinen, sondern seine literale, normale Bedeutung, also einen Senkrechtstrich als Senkrechtstrich oder einen Punkt als Punkt meinen. Das Maskierungszeichen ist in fast allen Fällen der Backslash. Erschwerend kommt hinzu, dass je nach Kontext (z.B. inner- oder außerhalb einer Zeichenklasse) verschiedene Zeichen verschiedene Bedeutungen haben und somit auch unterschiedliche Zeichen maskiert werden müssen. Die folgendenen Tabellen sollen als Übersicht über die jeweils zu maskierenden Zeichen dienen. Zunächst werden die Zeichen aufgeführt, welche außerhalb von Zeichenklassendefinitionen maskiert werden müssen.

Tabelle - Maskierung von Zeichen außerhalb eckiger Klammern (Zeichenklasse)
Zeichen Maskierung Grund Beispiel
/ \/ Wenn der Slash den regulären Ausdruck begrenzt, muss er innerhalb davon maskiert werden. /\/usr\/bin\/perl/
. \. Der Punkt steht in regulären Ausdrücken ansonsten für ein beliebiges anderes Zeichen (außer Zeilenumbrüchen). /Ende aus\./
+ \+ Das Pluszeichen steht ansonsten für ein oder mehrmaliges Vorkommen des davorstehenden Zeichens/Subpatterns. /\d\+\d/
* \* Das Sternzeichen steht ansonsten für kein, ein oder mehrmaliges Vorkommen des davorstehenden Zeichens/Subpatterns. /\*char/
? \? Das Fragezeichen steht ansonsten für kein oder einmaliges Vorkommen des davorstehenden Zeichens/Subpatterns. /Wie geht das\?/
^ \^ Das Dach- oder Hütchensymbol kann ansonsten bei Zeichenketten angeben, dass das nachfolgende Suchmuster am Anfang des Suchbereichs vorkommen muss. /ein \^ über dem Kopf/
$ \$ Das Dollarzeichen kann eine Variable einleiten oder bei Zeichenketten angeben, dass das voranstehende Suchmuster am Ende des Suchbereichs vorkommen muss. /Preis (US-Dollar): \d*\$/
@ \@ Der Klammeraffe kann eine Variable einleiten. /[a-z_0-9-]+\@localhost/
| \| Der Senkrechtstrich kann ansonsten alternative Ausdrücke auseinanderhalten. /find (.*) \| sort/
\ \\ Das Backslash würde ansonsten das nachfolgende Zeichen maskieren. /C:\\/
( ) \( \) Runde Klammern können ansonsten Teilausdrücke gruppieren und zum Merken einklammern. /\(Hinweis: (.*)\)/
[ \[ Öffnende eckige Klammern leiten ansonsten eine Zeichenklasse ein. /\$(.*)\[\d+]/
{ \{ Öffnende geschweifte Klammern leiten ansonsten eine Wiederholungs-Angabe ein. /\\frac 5\{23}/

Perl bietet fürs Maskieren dieser Zeichen (mit Ausnahme von $, @ und dem Begrenzungssymbol (Delimiter), meist /) noch eine Alternative, und zwar die Notation \Q...\E. Alles, was rechts von \Q (für quote) steht, wird literal verstanden, d.h. Metacharacters verlieren ihre Meta-Bedeutung. Dieses automatische Quoting läuft bis zum Ende des Regexp, es sei denn, es wird manuell vorher durch \E aufgehoben.

print 'match!' if 'Beispiele für Regexp-Metacharacters sind .?([{}]).'=~/\Q.?([{}])/;

\Q ist auch hilfreich, um den Inhalt von Variablen nur literal interpretieren zu lassen. Wenn beispielsweise eine Variable $suchausdruck = '.zip' lautet, so würde

'unzip'=~/$suchausdruck/

true liefern, weil der Punkt in '.zip' als Meta-Zeichen interpretiert wird. Diese Interpretation kann man durch

'unzip'=~/\Q$suchausdruck/

verhindern. Insbesondere bei Usereingaben kann das sinnvoll sein, um zu verhindern, dass schädlicher ausführbarer Code eingeschleust wird.

Innerhalb von Zeichenklassendefinitionen müssen andere Zeichen maskiert werden:

Tabelle - Maskierung von Zeichen innerhalb Zeichenklassendefinitionen
Zeichen Maskierung Grund Beispiel
/ \/ Wenn der Slash den regulären Ausdruck begrenzt, muss er auch innerhalb von Zeichenklassen maskiert werden. /[0-9\/]*/
- \- Das Minus steht innerhalb Zeichenklassen für einen Bis-Strich, wenn es nicht am Anfang oder Ende der Zeichenklassendefinition steht. Am Anfang bzw. Ende muss es also nicht maskiert werden. /[0\-a]/
^ \^ Das Dach- oder Hütchensymbol bedeutet, wenn es zu Beginn der Zeichenklassendefinition steht, dass die Zeichenklasse negiert wird. An anderen Stellen innerhalb der Zeichenklassendefinition braucht es nicht maskiert zu werden. /[\^0-9a-z+*\/-]/
$ \$ Das Dollarzeichen kann eine Variable einleiten. /[\@#\$][A-Za-z_]/
@ \@ Der Klammeraffe kann eine Variable einleiten. /[\@#\$][A-Za-z_]/
\ \\ Das Backslash würde ansonsten das nachfolgende Zeichen maskieren. /[a-z 0-9_\\]+/
] \] Schließende eckige Klammern beenden ansonsten die Zeichenklassendefinition. /[[\]]/

[Bearbeiten] Wie arbeiten Regexp-Engines?

Nach den beiden vorigen Abschnitten ist es nun an der Zeit, kurz und vereinfacht die Arbeitsweise von Regexp-Engines kennenzulernen. Wenn Sie wissen, wie Regexp-Engines „denken“, können Sie sich besser in sie hineinversetzen und auch besser ihr Anliegen so strukturieren und formulieren, dass die Engines es effizient umsetzen.

Versuchen Sie sich nun also vorzustellen, Sie seien eine Regexp-Engine. Zieren Sie sich nicht, sondern stellen Sie es sich ganz fest vor. Sie sind nun eine Regexp-Engine, die überprüfen soll, ob der reguläre Ausdruck /do.g/ bei der Zeichenkette 'ein ding dong doughnut' matcht. Als Regexp-Engine sehen Sie nicht den String als ganzes, so wie es ein Mensch tut, sondern Sie werden einzeln mit den Zeichen gefüttert, beginnend mit dem ersten Zeichen, hier also 'e'. Sie vergleichen dieses erste Zeichen mit dem ersten Symbol des regulären Ausdrucks /d/ und sehen keine Übereinstimmung:

'ein ding dong doughnut'
 ^
/do.g/
 ^

Deshalb wandern Sie in der Zeichenkette an die nächste Position zum 'i' und sehen wieder keine Übereinstimmung mit /d/.

'ein ding dong doughnut'
  ^
/do.g/
 ^

Das Gleiche passiert mit 'n' und ' '. Beim 'd' (von 'ding') finden Sie endlich eine Übereinstimmung

'ein ding dong doughnut'
     ^
/do.g/
 ^

und wandern nun sowohl in der Zeichenkette als auch im Regexp an die nächste Stelle. Sie vergleichen also 'i' mit /o/.

'ein ding dong doughnut'
      ^
/do.g/
  ^

Weil dies fehlschlägt, setzen Sie die aktuelle Position beim Regexp komplett zurück und schauen, ob vielleicht die erste Position /d/ das Zeichen 'i' matcht.

'ein ding dong doughnut'
      ^
/do.g/
 ^

Da auch dies nicht funktioniert, wandern Sie in der Zeichenkette weiter und vergleichen /d/ nacheinander vergeblich mit 'n', 'g' und ' '. Daraufhin erfolgt wieder ein Treffer, da /d/ wunderbar 'd' matcht.

'ein ding dong doughnut'
          ^
/do.g/
 ^

Sodann kann wieder sowohl im Regexp als auch in der Zeichenkette zum nächsten Zeichen gesprungen werden:

'ein ding dong doughnut'
           ^
/do.g/
  ^

Da auch /o/ das Zeichen 'o' matcht sowie /./ das Zeichen 'n' und letztlich /g/ das Zeichen 'g'

'ein ding dong doughnut'
             ^
/do.g/
    ^

ist der Regexp komplett abgearbeitet und somit die Aufgabe mit positivem Ergebnis gelöst: /do.g/ matcht 'dong' in der Zeichenkette 'ein ding dong doughnut'.

Grundsätzlich gilt: Wird zuerst der Regexp abgearbeitet, bedeutet das einen Treffer. Wird zuerst die Zeichenkette abgearbeitet, ohne dass der Regexp vollständig abgearbeitet worden ist, bedeutet das, dass kein Match erfolgen konnte.

Übrigens
Dass /do.g/ auch 'doug' gematcht hätte, ist hier unerheblich, da in diesem Beispiel ein Treffer bereits genügt.

Tipp: Die Stelle in der durchsuchten Zeichenkette, an der sich der Regexp-Zeiger aktuell befindet, lässt sich in Perl mittels der Funktion pos($str) verarbeiten. Beispiele dazu werden im Abschnitt über Modifiers angegeben.

Sie dürfen nun aufhören, sich vorzustellen, eine RegExp-Engine zu sein. Es ist jedoch für die Konstruktion regulärer Ausdrücke sowie das weitere Lesen der Dokumentation und spätestens bei einer Fehlersuche in einem Pattern empfehlenswert, hin und wieder gedanklich in diese Rolle zu schlüpfen.

[Bearbeiten] Reguläre Ausdrücke mit Alternativen

Sie können mehrere Suchausdrücke angeben und diese mit einem ODER-Symbol verknüpfen. Dann matcht der Ausdruck, sobald in einer Zeichenketten wenigstens eine der Alternativen vorkommt.

[Bearbeiten] Beispiel

Beispiel
#!/usr/bin/perl
 
use strict;
use warnings;
 
my $Text = 'Kaffee ohne Milch, aber mit Zucker.';
print "egal ob mit oder ohne\n" if $Text =~ /mit|ohne/;
$Text = 'Kaffee mit Milch';
print "sag ich doch: egal ob mit oder ohne\n" if $Text =~ /mit|ohne/;
Das Beispiel-Script deklariert eine Variable $Text mit dem Anfangswert Kaffee ohne Milch. Abhängig vom Erfolg des regulären Ausdrucks /mit|ohne/, der auf diese Variable angewendet wird, wird im aufrufenden Browser ausgegeben: egal ob mit oder ohne. Das Pipe-Symbol | teilt den regulären Ausdruck in zwei Alternativen auf, 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 anschließend angewendete gleiche reguläre Ausdruck führt wieder zum Erfolg, und es wird sag ich doch: egal ob mit oder ohne ausgegeben. Interessant ist im Zusammenhang mit dem letzten Abschnitt über die Arbeitsweise von Regexp-Engines, ob der Regexp /mit|ohne/ im String 'Kaffee ohne Milch, aber mit Zucker.' nun den Teilstring 'mit' oder den Teilstring 'ohne' matcht. Die Antwort ist einfach, wenn man weiß, dass bei ODER-Verknüpfungen bei jedem Zeichen der Zeichenkette sukzessive alle Alternativen ausprobiert werden (und nicht umgekehrt für jede Alternative der komplette String abgearbeitet wird). D.h. im Beispiel wird 'ohne' gematcht.

[Bearbeiten] Quantoren I

Musterwiederholungen können Sie mit Quantoren (engl. quantifiers) kennzeichnen. Auch wenn in diesem Abschnitt nur auf Wiederholungen einzelner Zeichen eingegangen wird, sei an dieser Stelle bereits darauf hingewiesen, dass die hier vorgestellten Quantoren nicht nur auf einzelne Zeichen beschränkt sind, sondern auch auf Gruppierungen angewendet werden können, wie sie im nächsten Abschnitt vorgestellt werden.

Tabelle - Beispiele für Quantoren
Nr. Regulärer Ausdruck matcht
1. /x{10,20}/ 10 bis 20 'x' in Folge
2. /x{10}/ genau 10 'x' in Folge
3. /x{10,}/ mindestens 10 'x' in Folge
4. /aus?/ 'aus' usw. - aber auch 'au' z.B. in der Zeichenkette 'auf'
5. /a+/ 'a' und 'aa' und 'aaaaa' (ein oder mehr 'a')
6. /a*/ 'a', 'aa' und 'aaaaa', aber auch den Leerstring '' z.B. in der Zeichenkette 'b' (kein oder mehr 'a')
7. /Ha[enu]+s/ 'Haus', 'Hans' und 'Hannes', aber nicht 'Has' (ein oder mehr 'u', 'n' oder 'e')
8. /Ha[enu]*s/ 'Has', 'Haus', 'Hans' und 'Hannes' (beliebig viele Zeichen 'u', 'n' oder 'e')
9. /Ha[enu]?s/ 'Haus', 'Hans' und 'Has' z.B. in 'Mein Name ist Hase.'
10. /x.{2}y/ 'xxxy' oder 'xaby' usw. (zwei beliebige Zeichen zwischen 'x' und 'y', außer \n)
11. /^\s*$/ Zeilen, die nur aus Leerzeichen oder anderem Whitespace bestehen oder leer sind

Allgemein werden für Wiederholungen geschweifte Klammern nach dem Schema {n, m} verwendet, wobei n für die Mindestanzahl an Vorkommnissen und m die maximale Anzahl an Vorkommnissen bedeutet, siehe Beispiel (1.). Wird das m wie in Beispiel (3.) weggelassen, so bedeutet dies, dass keine maximale Anzahl vorgegeben wird, d.h. es müssen einfach mind. n Vorkommnisse (hintereinander) vorhanden sein. Möchten sie genau eine vorgegebene Anzahl an Wiederholungen matchen,, d.h. heißt m=n, so können Sie dafür die Syntax {n} wie in den Beispiel (2.) und (10.) verwenden. Für einige Kombinationen von n und m gibt es abkürzende Schreibweisen, wie aus der nachfolgenden Tabelle ersichtlich.

Tabelle - gängige abkürzende Quantoren
Klammerschreibweise Abkürzung
{0,1}  ?
{0,} *
{1,} +

Das Fragezeichen ? bedeutet also in einem regulären Ausdruck: Das Zeichen (oder die Gruppe von Zeichen, siehe nächster Abschnitt) vor dem Fragezeichen oder auch nicht. Siehe dazu Beispiele (4.) und (9.).

Das Pluszeichen + bedeutet: Ein oder mehrere Vorkommnisse des Zeichens, das vor dem Pluszeichen steht. Siehe dazu Beispiele (5.) und (7.).

Das Sternzeichen * bedeutet: keines, eines oder mehrere Vorkommnisse des Zeichens, das vor dem Sternzeichen steht. Siehe dazu Beispiele (6.), (8.) und (10.).

[Bearbeiten] Teilausdrücke gruppieren oder merken durch Klammerung

Mithilfe von Klammerung einzelner Teile eines regulären Ausdrucks können Sie Teilmuster speichern (capture buffers) und an einer späteren Stelle wiederverwenden (Rückreferenzierung oder back referencing). Sie können aber die Klammern auch einfach zur Grupperierung von Teilausdrücken verwenden, um z.B. in Kombination mit dem Pipe-Symbol alternative Teilausdrücke zu bilden.

Die folgende Tabelle zeigt einige Möglichkeiten der Gruppierung sowie der Rückreferenzierung.

Tabelle - Beispiele für einfache reguläre Ausdrücke mit Klammerung
Nr. Regulärer Ausdruck Wirkung
1. /\d\d:\d\d:\d\d/ matcht 3 Zifferpaare, die durch Doppelpunkte separiert sind.
2. /(\d\d):\d\d:\1/ wie Beispiel 1., wobei das erste Ziffernpaar mit dem dritten identisch sein muss.
3. /(\d\d):\d\d:\g{1}/ wie Beispiel 2., aber mit alternativer Notation.
4. /((\d)\2):(\d)\3:\1/ wie Beispiel 1., aber mit der Einschränkung, dass die Ziffern dem Schema "xx:yy:xx" entsprechen müssen.
5. /((\d)\g{-1}):(\d)\g{-1}:\g{-3}/ wie Beispiel 4., aber mit alternativer Notation.
6. /(?'erstespaar'(?'ersteziffer'\d)\k'ersteziffer'):
(?'erstemittlereziffer'\d)\k'erstemittlereziffer':\k'erstespaar'/
wie Beispiel 4., aber mit weiterer, alternativer Notation.
7. /(\d\d:)+\d\d/ matcht eine Folge von Ziffernpaaren, die jeweils mit Doppelpunkten separiert sind.
8. /(?:\d\d:)+\d\d/ wie Beispiel 7., allerdings wird der geklammerte Ausdruck nicht zwischengespeichert.

Mit einfachen runden Klammern werden Teilausdrücke als solche gekennzeichnet und zudem die von ihnen gematchte Teilzeichenkette zwischengespeichert. Auf diese zwischengespeicherten Submatches können Sie standardmäßig mit \1, \2, \3 usw. zugreifen; siehe Beispiele (2. und 4.). Die Ordnung erfolgt dabei anhand der Reihenfolge der öffnenden Klammern. Einige moderne Regexp-Implementierungen wie beispielsweise die von Perl ab Version 5.10 bieten außerdem die Möglichkeit, die Teilzeichenketten zu bennenen (named buffers) wie in Beispiel (6.). Benannt werden Ausdrücke mit (?<name>ausdruck) oder (?'name'ausdruck). Zugreifen können Sie dann mittels \k<name> bzw. \k'name' oder auch mit \g{name}. Die Namen unterliegen den gleichen Regeln wie andere Variablennamen. In Perl 5.10+ können Sie auch mit \g{n} auf die konventionellen nummerierten Submatches referenzieren wie in Beispiel (3.), wobei die Zahl n wie im Beispiel (5.) sogar negativ sein darf und dann die Rückreferenz relativ aufgefasst wird, sodass damit auf den -n-ten vorigen Submatch verwiesen wird.

In Beispiel (7.) werden Klammern mit einem Quantor kombiniert. Der Quantor bezieht sich hier also auf den kompletten eingeklammerten Ausdruck. Wenn keine Rückreferenz benötigt wird, kann Perl dazu veranlasst werden, den eingeklammerten Ausdruck nicht zwischenzuspeichern, was laut Manual eine schnellere Ausführung zur Folge haben soll.[1] Ein non-capturing Pattern wird einfach durch ein Fragezeichen und einen Doppelpunkt zu Beginn des Teilausdrucks gekennzeichnet, wie in Beispiel (8.). Sie sollten sich angewöhnen, immer non-capturing Patterns zu verwenden, wenn Sie keine Referenzen darauf erstellen möchten. Hauptgrund dafür ist, dass Sie vor allem bei komplexeren Ausdrücken auf diese Weise einen besseren Überblick über die wirklich benötigten zwischengespeicherten Teilzeichenketten behalten.

Das nächste Beispiel zeigt, dass man auch außerhalb der regulären Ausdrucks auf die zwischengespeicherten Strings zugreifen kann.

[Bearbeiten] Beispiel

Beispiel
#!/usr/bin/perl
use strict;
use warnings;
 
my $satz = 'Aus diesem Satz soll das Datum 20060606T05:23:42 extrahiert und aufgeschlüsselt werden.';
$satz =~ /(\d{4})(\d\d)(\d\d)T(\d\d):(\d\d):(\d\d)/;
my $jahr = $1;
my $monat = $2;
my $tag = $3;
my $stunden = $4;
my $minuten = $5;
my $sekunden = $6;
my @monate = ('Januar', 'Februar', 'März', 'April', 'Mai', 'Juni', 'Juli', 'August', 'September', 'Oktober', 'November', 'Dezember');
print "Das extrahierte Datum ist $stunden:$minuten:$sekunden Uhr am $tag. $monate{$monat} $jahr.\n";
Im Beispiel wird zuerst die Variable $satz gesetzt. In $satz ist ein Datum enthalten, das in der darauffolgenden Anweisung von einem langen regulären Suchausdruck gematcht wird. Der reguläre Ausdruck versucht, das gesamte typische Datum-Uhrzeit-Muster nach ISO zu erfassen. Die Nutzdaten darin, also Jahr, Monatsname, Monatstag, Stunden, Minuten und Sekunden werden innerhalb des regulären Ausdrucks geklammert. Jeden Inhalt dieser Klammern merkt sich Perl und stellt ihn in den vordefinierten Variablen $1, $2, $3 usw. zur Verfügung. Die anschließend deklarierten Variablen holen sich die Werte aus den Klammern, indem ihnen die entsprechenden vordefinierten Variablen zugewiesen werden.

Das Array @monate wird zum Zweck eines deutschsprachigen Datum-Uhrzeit-Formats verwendet. Das Script gibt am Ende aus:

Das extrahierte Datum ist 05:23:42 Uhr am 06. Juni 2006.
Beachten Sie: Auch auf benannte Submatches können Sie außerhalb des regulären Ausdrucks zugreifen. Jene liegen in Form eines Hashes %+ vor, sodass Sie mit $+{''name>''} auf die jeweiligen Submatches zugreifen können.

[Bearbeiten] Quantoren II - genügsam, gierig, gefräßig

Sie haben bisher nur die konventionellen, sog. gierigen (engl. greedy) Regexps kennengelernt. Wenn Sie beispielsweise bei einem String wie 'Bruder Jakob, Bruder Jakob.' den Regexp /Bru.*kob/ anwenden, dann wird hier von /.*/ der Teil 'der Jakob, Bruder Ja' gematcht, also der längste mögliche String. Allerdings kommt es hin und wieder vor, dass man lieber nur den kürzest möglichen String matchen möchte, also im Beispiel 'der Ja'. Dies ist mithilfe der genügsamen (engl. non-greedy) Quantoren möglich. Ein genügsamer Quantor ist einfach ein normaler Quantor, dem ein Fragezeichen angehängt wird; in unserem Beispiel also /Bru.*?kob/.

Und es existiert noch eine dritte Sorte, die possessiven Quantoren (engl. possessive quantifiers). Da jene allerdings bloß eine andere Schreibweise für atomic grouping darstellen, wird darauf erst im Abschnitt #Atomic Grouping eingegangen.

Tabelle - Quantoren
Klammerschreibweise Bedeutung
{n,m} mind. n, max. m Vorkommnisse (so viel wie möglich)
{n,m}? mind. n, max. m Vorkommnisse (so wenig wie möglich)
{n,m}+ mind. n, max. m Vorkommnisse (so viel wie möglich, ohne gematchtes wieder freizugeben)

[Bearbeiten] Beispiel

Beispiel
#!/usr/bin/perl
use strict;
use warnings;
 
my $HTML_Zeile = "<html><head><title>Testausgabe</title></head><body><h1>Überschrift</h1></body></html>";
 
$HTML_Zeile =~ /(^<.+>)/;
my $gierig = $1;
$HTML_Zeile =~ /(^<.+?>)/;
my $genuegsam = $1;
 
print "Gierige Version:   '$gierig'.\n";
print "Genügsame Version: '$genuegsam'.\n";
Das Beispiel-Script demonstriert die Gier regulärer Ausdrücke und zeigt auch, wie sich diese Gier unterbinden lässt. Eine Variable namens $HTML_Zeile wird deklariert und erhält als Anfangswert den Code einer kompletten kleinen HTML-Datei. Anschließend wird diese Variable 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 in der Variable $gierig gespeichert. Anschließend wird die Prozedur noch einmal wiederholt. Diesmal ist der reguläre Ausdruck nur geringfügig 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 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ächstmöglichen >-Zeichens.

[Bearbeiten] Rangfolge in regulären Ausdrücken

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

  1. Rangstufe: Klammerung
  2. Rangstufe: Quantoren
  3. Rangstufe: Zeichen/Zeichenketten, ...
  4. Rangstufe: Alternativen via |

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.

Tabelle - Beispiele für kombinierte reguläre Ausdrücke mit Klammerung
Nr. Regulärer Ausdruck Wirkung
1. /a|bc|d/ matcht 'a' oder 'bc' oder 'd'.
2. /(?:a|b)(?:c|d)/ matcht 'ac' oder 'ad' oder 'bc' oder 'bd'
3. /lecker (?:(?:zwetschgen|hunde|)kuchen|gerstenkaltschorle)/ matcht 'lecker zwetschgenkuchen', 'lecker hundekuchen', 'lecker gerstenkaltschorle', aber auch einfach 'lecker kuchen'

Laut der Rangfolge haben Zeichen bzw. Zeichenketten Vorrang vor dem Trennzeichen für Alternativen. Mithilfe von Klammern können Sie eine andere Bewertung erzwingen (siehe Beispiel 1. und 2.).

Wenn Sie sich die entsprechenden Teilausdrücke merken wollen, können Sie stattdessen einfache Klammern (...) benutzen statt (?:...), im Beispiel (2.) wäre das (a|b)(c|d).

In Beispiel (3.) sind zwei Klammerausdrücke verschachtelt. Im Subpattern (?:zwetschgen|hunde|) werden durch die Pipe-Symbole | tatsächlich drei Alternativen angegeben, nämlich 'zwetschgen', 'hunde' und '' also der leere String. Es handelt sich hierbei also um eine alternative Notation zu (?:zwetschgen|hunde)?.

[Bearbeiten] Modifiers

Hinter dem beendenden Begrenzerzeichen (normalerweise: Slash) eines regulären Ausdrucks können noch ein oder mehrere Buchstaben notiert werden - sogenannte Modifiers oder manchmal auch Flags genannt. Damit können Sie das Verhalten der Suche zusätzlich beeinflussen. Mit einer Notation wie /aus/i suchen Sie beispielsweise unabhängig von Groß- und kleinschreibung nach dem Vorkommen von aus, AuS usw. Die folgende Tabelle listet die möglichen Modifiers auf.

Tabelle - Modifiers von regulären Ausdrücken
Modifier Eselsbrücke Bedeutung
i case-insensitive Groß-/Kleinschreibung ignorieren.
m multi-line Interpretation des Strings als mehrere Zeilen. Die Anchors ^ und $ matchen damit nicht mehr nur String-Anfange bzw. -Ende, sondern Zeilen-Anfang bzw. -Ende. Unabhängig vom /m-Modifer kann Ein String-Anfang stets mit \A und ein String-Ende mit \z gematcht werden. Zudem gibt es noch mit \Z die Möglichkeit, ein String-Ende oder die Position vor einem abschließenden Newline-Zeichen zu matchen.
s single line Punkt jedes Zeichen, auch Zeilenumbrüche(!), matchen lassen.
e evaluate Evaluation von Code. Führt bei Ersetzungen die Ersatzzeichenkette als Perl-Code aus.
o compile only once Falls Variablen im Pattern vorkommen, werden jene nur einmal (statt jedes Mal) aufgelöst. Dies konnte in alten Perl-Versionen Schleifendurchläufe beschleunigen. Seit Perl 5.6 geschieht dies automatisch und der /o-Modifier hat keine geschwindigkeitsrelevante Aufgabe mehr und wird deswegen auch nicht mehr im Perl-RegExp-Manual erwähnt.
x extend legibility bessere Lesbarkeit zulassen durch Kommentare und Whitespace.
g global globales Matchen, d.h. alle Vorkommnisse finden.
c current position Bei einem auftretenden Fehler nicht die Suchposition zurücksetzen.
p preserve macht explizit den gematchten Teilstring {$^MATCH} sowie die beiden Reststrings (links ${^PREMATCH} und rechts ${^POSTMATCH} davon) für etwaige Verwendung nach dem eigentlichen Matching verfügbar.
d default oder depends wendet Unicode-Regeln automatisch nur dann an, wenn sie erzwungen werden. (Seit Perl 5.14 vorhanden)
u Unicode behandelt das Pattern nach Unicode-Regeln. (Seit Perl 5.14 vorhanden)
a ASCII das Gleiche wie der u-Modifier, jedoch ohne Unicode-Regeln auf \d, \s, \w und die POSIX-Zeichenklassen anzuwenden. (Seit Perl 5.14 vorhanden)
l current locale benutzt die aktuellen locale-Einstellungen. (Seit Perl 5.14 vorhanden)

Neben der oben genannten Notation /pattern/i gibt es noch eine alternative, die es auch ermöglicht, nur auf Teile des Patterns begrenzt zu sein: /(?i)pattern/ oder /(?i:pattern)/. Mithilfe dieser Notation ist es auch möglich, bestehende Modifiers für einen Teilbereich zu deaktivieren: /pa(?-i:tt)ern/i verlangt beispielsweise trotz des /i-modifiers, dass der Teilstring, der vom Subpattern (?-i:tt) gematcht wird, kleingeschrieben ist.

Die Modifiers können auch kombiniert werden. Einige Beispiele sollen die Funktionsweisen verdeutlichen. Bei den folgenden Beispielen werden verschiedene reguläre Ausdrücke stets auf denselben String angewendet.

Beachten Sie: Einige der Modifiers von Perl finden sich auch in den Regexp-Implementierungen anderer Sprachen, aber nicht alle.
  • In JavaScript gibt es mindestens die Modifiers m, i, g.
  • In PHP gibt es die Modifiers s, m, i, x, e, A, D, S, U, X, J, u.[2]
  • In Python werden sie flags genannt und werden als Funktionsparameter re.S, re.I, re.L, re.M, re.U, re.X notiert.[3]
  • In der Boost Library für C++ werden die options ganz anders notiert und können nur unter bestimmten Bedingungen benutzt werden.[4]
  • In Java werden die flags ebenfalls über Konstanten gesetzt.[5]

[Bearbeiten] Beispiel für die Anwendung des /i-Modifiers

Beispiel
#!/usr/bin/perl
use strict;
use warnings;
 
my $str = 'Gestern ist mir ein Waschlappen vom Haken gefallen.
Daraufhin habe ich ihn wieder auf den Waschlappenhaken gehängt.';
 
print "/i-Modifier\n";
my $counter = 0;
while($str=~/([a-z]{3}) waschlappen/i){
  print " '$1'\n";     
  last if ++$counter>4;
}
Output:
/i-Modifier
 'ein'
 'ein'
 'ein'
 'ein'
 'ein'
Dieses kleine Script gibt immer wieder den String "ein" aus, solange bis die Schleife nach dem fünften Durchlauf abgebrochen wird. Ohne Anwendung des /i-Modifiers würde die Schleife kein einziges Mal durchlaufen, da "waschlappen" (kleingeschrieben) nicht im durchsuchten String vorkommt.

[Bearbeiten] Beispiel für die Anwendung des /g-Modifiers

Beispiel
#!/usr/bin/perl
use strict;
use warnings;
 
my $str = 'Gestern ist mir ein Waschlappen vom Haken gefallen.
Daraufhin habe ich ihn wieder auf den Waschlappenhaken gehängt.';
 
print "/g-Modifier\n";
while($str=~/([a-z]{3}) waschlappen/ig){
  print " '$1' vor pos ".pos($str)."\n";
}
print " pos ist jetzt nicht mehr definiert.\n" if not defined pos($str);
Output:
/g-Modifier
 'ein' vor pos 31
 'den' vor pos 101
 pos ist jetzt nicht mehr definiert.
Das Gleiche wie oben, jetzt mit zusätzlichem /g-Modifier. Die Schleife gibt 'ein' vor pos 31 und 'den' vor pos 101 aus. Ein Abbruch der Schleife erfolgt, sobald das Pattern nicht mehr matcht, d.h., wenn das Ende des Strings erreicht wird.

Die letzte Zeile demonstriert, dass die Suchposition pos($str) nach dem letzten Schleifendurchlauf, in dem ja kein Matching mehr stattfand, verworfen (d.h. auf undef gesetzt) wird. Verhindern können Sie dies durch Anwendung des /c-Modifiers, was in einem der nachfolgenden Beispiele demonstriert wird.

[Bearbeiten] Beispiel für die Anwendung des /x-Modifiers

Beispiel
#!/usr/bin/perl
use strict;
use warnings;
 
my $str = 'Gestern ist mir ein Waschlappen vom Haken gefallen.
Daraufhin habe ich ihn wieder auf den Waschlappenhaken gehängt.';
 
print "/x-Modifier\n";
while($str=~/([a-z]{3})  #  drei Buchstaben
             \           #  ein Leerzeichen
             waschlappen #  der String "waschlappen"
             /igx){
  print " '$1' vor pos ".pos($str)."\n";
}
print " pos ist jetzt nicht mehr definiert\n" if not defined pos($str);
Output:
/x-Modifier
 'ein' vor pos 31
 'den' vor pos 101
 pos ist jetzt nicht mehr definiert
Das Gleiche wie im letzten Beispiel, allerdings noch mit zusätzlichem /x-Modifier. Die Schleife gibt wie oben 'ein' vor pos 31 und 'den' vor pos 101 aus. Durch den /x-Modifier können jetzt Kommentare innerhalb des Patterns bequem via # geschrieben werden. Whitespace wird ignoriert. Sollen eine literale Raute oder ein Whitespace-Zeichen wie hier im Beispiel das Leerzeichen gematcht werden, müssen Sie jene im Pattern maskieren.

[Bearbeiten] Beispiel für die Anwendung des /s-Modifiers

Beispiel
#!/usr/bin/perl
use strict;
use warnings;
 
my $str = 'Gestern ist mir ein Waschlappen vom Haken gefallen.
Daraufhin habe ich ihn wieder auf den Waschlappenhaken gehängt.';
 
print "/s-Modifier\n";
print " ohne /s-modifier: Text erscheint nicht!\n" if $str=~/waschlappen.*waschlappen/i;
print " mit /s-modifier:  match!\n" if $str=~/waschlappen.*waschlappen/si;
Output:
/s-Modifier
 mit /s-modifier:  match!
Beim ersten regulären Ausdruck, wird geprüft, ob in irgendeiner Zeile, das Wort "waschlappen" (kleingeschrieben) zwei mal vorkommt. Beim zweiten Regexp wird geprüft, ob im gesamten String zweimal das Wort vorkommt.

[Bearbeiten] Beispiel für die Anwendung des /m- und des /c-Modifiers

Beispiel
#!/usr/bin/perl
use strict;
use warnings;
 
my $str = 'Gestern ist mir ein Waschlappen vom Haken gefallen.
Daraufhin habe ich ihn wieder auf den Waschlappenhaken gehängt.';
 
print "/m-Modifier\n";
while($str=~/^([a-z]+)/img){
  print " '$1' vor pos ".pos($str)."\n";
}
print " pos ist jetzt nicht definiert\n" if not defined pos($str);
 
print "\n/ohne /m-, aber mit /c-modifier\n";
while($str=~/^([a-z]+)/igc){
  print " '$1' vor pos ".pos($str)."\n";
}
print ' pos ist jetzt '. pos($str)."\n";
 
print "\nnoch mal nur mit /m-Modifier\n";
while($str=~/^([a-z]+)/img){
  print " '$1' vor pos ".pos($str)."\n";
}
print " pos ist jetzt nicht definiert\n" if not defined pos($str);
Output:
/m-Modifier
 'Gestern' vor pos 7
 'Daraufhin' vor pos 61
 pos ist jetzt nicht definiert

/ohne /m-, aber mit /c-modifier
 'Gestern' vor pos 7
 pos ist jetzt 7

noch mal nur mit /m-Modifier
 'Daraufhin' vor pos 61
 pos ist jetzt nicht definiert

Die erste Schleife gibt 'Gestern' vor pos 7 und 'Daraufhin' vor pos 61 aus. Anschließend wird wieder ausgegeben, dass pos($str) nicht mehr definiert ist.

Die zweite Schleife gibt 'Gestern' vor pos 7 aus und lässt den Regexp-Cursor hinter dem gematchten Gestern. Es wird nach der Schleife ausgegeben, dass pos($str) noch immer auf 7 steht.

Die dritte Schleife gibt nun, da pos($str) noch immer auf 7 steht, nur den zweiten Match aus, also 'Daraufhin' vor pos 61. Da in der dritten Schleife der /c-Modifier nicht verwendet wird, ist nach der dritten Schleife pos($str) wieder verworfen.

[Bearbeiten] Beispiel für die Anwendung des /o-Modifiers

Beispiel
#!/usr/bin/perl
use strict;
use warnings;
 
my $str = 'Gestern ist mir ein Waschlappen vom Haken gefallen.
Daraufhin habe ich ihn wieder auf den Waschlappenhaken gehängt.';
 
print "/o-Modifier\n";
my $pattern = 'gehängt';
use Time::HiRes qw(time);
my $time = Time::HiRes::time();
$str=~/$pattern/i for 0..10_000_000;
my @time_diff;
$time_diff[0] = Time::HiRes::time()-$time;
print ' ohne /o-modifier: '.$time_diff[0]." sekunden.\n";
$time = time;
$str=~/$pattern/io for 0..10_000_000;
$time_diff[1] = Time::HiRes::time()-$time;
print ' mit /o-modifier:  '.$time_diff[1]." sekunden.\n";
printf(" mit /o-modifier:  %3.1f%% schneller.\n", (1-$time_diff[1]/$time_diff[0])*100);
Output (Perl 5.10.0):
/o-Modifier
 ohne /o-modifier: 6.69600605964661 sekunden.
 mit /o-modifier:  6.55151700973511 sekunden.
 mit /o-modifier:  2.2% schneller.
In diesem Beispiel wird Time::HiRes eingebunden, um genauer als nur sekundengenau die verstrichene Zeit messen zu können. Seit Perl-Version 5.6 bewirkt der o-Modifier hier keine wirkliche Verbesserung mehr, da ab dieser Version reguläre Ausdrücke, die eine Variable enthalten, automatisch nur einmal kompiliert werden, wenn sich das Pattern nicht ändert.

[Bearbeiten] Einbeziehung des Kontexts via Assertions

Eine häufige Problemstellung, auf die jeder (sich mit regulären Ausdrücken beschäftigende) früher oder später trifft, bilden Fälle, in denen eine Teilzeichenkette A gesucht wird, der eine andere Teilzeichenkette B vorangeht oder folgt, wobei B aber selbst nicht im Suchergebnis enthalten sein soll. Wenn Sie bspw. in einem String alle Wörter finden wollen, die auf "lappen" enden, könnten Sie dies mit dem Ausdruck /\w+lappen\b/i, also z.B.

  # $str wird als gegebener String angenommen
  my @fundstellen = ($str=~/\w+lappen\b/gi);

versuchen. Wenn jedoch Wörter mit Bindestrichen vorkommen können, dann würde obiger Regexp versagen, da z.B. "Waschlappen-Haken" nicht auf "lappen" endet, aber vom obigen Regexp gematcht würde. Sie könnten also einen nächsten Versuch mit /\w+lappen\b[^-]/i unternehmen. Mit diesem Regexp allerdings würde bei einem String, bei dem auf "lappen" nichts mehr folgt, dieses letzte Wort nicht gematcht werden, da wegen /[^-]/ dahinter ein Zeichen verlangt wird, das kein Bindestrich ist. Um das Problem zu lösen, möchte man eigentlich gerne die Möglichkeit haben, per Regexp irgendwie auszudrücken, dass ein String gesucht wird, dem ein anderer String nicht folgt, im Beispiel: Gesucht wird "lappen", ohne dass das nächste Zeichen ein Buchstabe oder ein Bindestrich ist.

Und ebendies liefert ein Regexp-Konstrukt mit der schönen, kurzen, einprägsamen Bezeichnung zero-width negative look-ahead assertion. Der Regexp sähe damit so aus: /\w+lappen(?![a-z-])/i. Der Bestandteil (?![a-z-]) ist die Assertion. Das Attribut zero-width bedeutet, dass das Pattern /[a-z-]/ zwar als Regexp-Pattern ausgewertet wird, es jedoch keinen Einfluss auf den Positionszeiger im String hat, wie er im Abschnitt Wie arbeiten Regexp-Engines? beschrieben wurde. negative bedeutet, dass das Pattern nicht matchen soll. Und look-ahead bezieht sich lediglich auf die Leserichtung von Regexp-Engines, die glücklicherweise identisch mit der unsrigen ist. Somit ist nach rechts = voraus (engl. ahead) und nach links = dahinterliegend (engl. behind) Es gibt vier verschiedene Arten von Assertions:

Tabelle - Modifiers von regulären Ausdrücken
Code Bezeichnung
(?=...) zero-width positive look-ahead assertion
(?!...) zero-width negative look-ahead assertion
(?<=...) zero-width positive look-behind assertion
(?<!...) zero-width negative look-behind assertion


ToDo:    (weitere ToDos)

erklaerung

[Bearbeiten] 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.

[Bearbeiten] Beispiel

Beispiel
#!/usr/bin/perl
 
use strict;
use warnings;
 
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 eine Variable, in der eine Zeichenkette gespeichert ist, so wie etwa $Text im obigen Beispiel 1. Diese Variable wird mit dem Operator =~ an die Ersetzung gebunden, d.h. der Suche-Ersetze-Vorgang gilt für den Inhalt der Variable. Dahinter notieren Sie die Ersetzung. Sie wird durch ein kleines s eingeleitet. Nach dem s notieren Sie das erste Begrenzerzeichen (per Voreinstellung ein Slash), und danach das Suchmuster, das mit dem zweiten Begrenzerzeichen abgeschlossen wird. Danach folgen das Zeichen oder die Zeichenfolge, mit dem/mit der die Fundstellen ersetzt werden sollen, abgeschlossen wird dieses Ersetzungsmuster mit dem dritten Begrenzerzeichen.

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 der Variable $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.

[Bearbeiten] Beispiel

Beispiel
#!/usr/bin/perl
 
use strict;
use warnings;
 
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

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

[Bearbeiten] Beispiel

Beispiel
#!/usr/bin/perl
 
use strict;
use warnings;
 
my $Text = "Dieses Script dreht alle Wörter um";
$Text =~ s/(\w+)/reverse $1/ge;
 
print "$Text\n";
Erläuterung

In diesem Beispiel werden in $Text alle Wörter mithilfe des e-Modifiers und der reverse-Funktion umgedreht. Das Ergebnis wird zur Kontrolle ausgegeben.

[Bearbeiten] 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.

[Bearbeiten] Beispiel

Beispiel
#!/usr/bin/perl
 
use strict;
use warnings;
 
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";
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 Such- als auch das Ersetzungsmuster 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 eine Variable 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 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 zu eigen gemacht. Der Variable $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 Zeichenwerten 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).

[Bearbeiten] ToDo

  • bei den perlbeispielen fehlen noch die "so sieht's aus"-umsetzungen
  • auf javascript, php und python wurde noch keine ruecksicht genommen. js, php, python usw. koennen nicht alles, was perl kann.
  • abschnitt "einzelne zeichen": \v, \h, \R: evtl. separate tabelle; evtl. hinweis auf verschiedene sprachen
  • assertions
  • conditional statements
  • atomic grouping
  • anchors a la \G

[Bearbeiten] Tabelle der möglichen Meta-Character

Code Bedeutung erklärt im Abschnitt
\000 octale Escape-Sequenz #Reguläre Ausdrücke für einzelne Zeichen
\1 Backreference #Teilausdrücke gruppieren oder merken durch Klammerung
\a Alarm/bell #Reguläre Ausdrücke für einzelne Zeichen
\A begin of string #Modifiers
\b word boundary (backspace in einer zeichenklasse) #Reguläre Ausdrücke für Zeichenketten
\B alles ausser word boundary #Reguläre Ausdrücke für Zeichenketten
\cX control-X #Reguläre Ausdrücke für einzelne Zeichen
\C single octet, even under UTF-8 fehlt noch
\d ziffer [0-9] #Reguläre Ausdrücke für einzelne Zeichen
\D nicht-ziffer [^0-9] #Reguläre Ausdrücke für einzelne Zeichen
\e das Escape-Zeichen #Reguläre Ausdrücke für einzelne Zeichen
\E Deaktivieren von \Q, \L oder \U #Maskierung von Zeichen in regulären Ausdrücken
\f form feed #Reguläre Ausdrücke für einzelne Zeichen
\g named backreference #Teilausdrücke gruppieren oder merken durch Klammerung
\G Matcht bei pos() fehlt noch
\h horizontal whitespace fehlt noch
\H not horizontal whitespace fehlt noch
\k named backreference #Teilausdrücke gruppieren oder merken durch Klammerung
\K Keep the stuff left of the \K, don't include it in $& fehlt noch
\l Lowercase next character fehlt noch
\L Lowercase till \E fehlt noch
\n newline #Reguläre Ausdrücke für einzelne Zeichen
\N{} Named (Unicode) character #Reguläre Ausdrücke für einzelne Zeichen
\p{}, \pP Character with a Unicode property #Reguläre Ausdrücke für einzelne Zeichen
\P{}, \PP Character without a Unicode property #Reguläre Ausdrücke für einzelne Zeichen
\Q Quotemeta till \E #Maskierung von Zeichen in regulären Ausdrücken
\r return #Reguläre Ausdrücke für einzelne Zeichen
\R linebreak fehlt noch
\s whitespace #Reguläre Ausdrücke für einzelne Zeichen
\S non-whitespace #Reguläre Ausdrücke für einzelne Zeichen
\t tab #Reguläre Ausdrücke für einzelne Zeichen
\u Titlecase next character fehlt noch
\U Uppercase till \E fehlt noch
\v vertival whitespace fehlt noch
\w Character class for word characters #Reguläre Ausdrücke für einzelne Zeichen
\W Character class for non-word characters #Reguläre Ausdrücke für einzelne Zeichen
\x{}, \x00 Hexadecimal escape sequence #Reguläre Ausdrücke für einzelne Zeichen
\X Extended Unicode "combining character sequence" fehlt noch
\z end of string #Modifiers
\Z end of string or before newline #Modifiers
^ begin of line (or negate char class) #Reguläre Ausdrücke für einzelne Zeichen
$ end of line or before newline #Reguläre Ausdrücke für Zeichenketten
| or #Reguläre Ausdrücke mit Alternativen
&` fehlt noch
&? fehlt noch
\ escaping char #Maskierung von Zeichen in regulären Ausdrücken
. non-newline (any char, when s-modifier is set) #Reguläre Ausdrücke für einzelne Zeichen
{n} n times, greedy #Quantoren I
{n}? n times, non-greedy #Quantoren II - genügsam, gierig, gefräßig
{n}+ n times, possessive #Quantoren II - genügsam, gierig, gefräßig
{n,} at least n times, greedy #Quantoren I
{n,}? at least n times, non-greedy #Quantoren II - genügsam, gierig, gefräßig
{n,}+ at least n times, possessive #Quantoren II - genügsam, gierig, gefräßig
{n,m} at least n times, at most m times, greedy #Quantoren I
{n,m}? at least n times, at most m times, non-greedy #Quantoren II - genügsam, gierig, gefräßig
{n,m}+ at least n times, at most m times, possessive #Quantoren II - genügsam, gierig, gefräßig
 ? 0 or 1 time, greedy #Quantoren I
 ?? 0 or 1 time, non-greedy #Quantoren II - genügsam, gierig, gefräßig
 ?+ 0 or 1 time, possessive #Quantoren II - genügsam, gierig, gefräßig
+ at least 1 time, greedy #Quantoren I
+? at least 1 time, non-greedy #Quantoren II - genügsam, gierig, gefräßig
++ at least 1 time, possessive #Quantoren II - genügsam, gierig, gefräßig
* at least 0 times, greedy #Quantoren I
*? at least 0 times, non-greedy #Quantoren II - genügsam, gierig, gefräßig
*+ at least 0 times, possessive #Quantoren II - genügsam, gierig, gefräßig
[] Zeichenklasse #Reguläre Ausdrücke für einzelne Zeichen
() Gruppierung #Teilausdrücke gruppieren oder merken durch Klammerung
(?:) non-capturing grouping #Teilausdrücke gruppieren oder merken durch Klammerung
(?imsx-imsx:) modifier combined with non-capturing grouping
(?=) zero-width positive look-ahead #Einbeziehung des Kontexts via Assertions
(?!) zero-width negative look-ahead #Einbeziehung des Kontexts via Assertions
(?<=) zero-width positive look-behind #Einbeziehung des Kontexts via Assertions
(?<!) zero-width negative look-behind #Einbeziehung des Kontexts via Assertions
(?>) atomic grouping
(?#) comment
(?pimsx-imsx) modifier
(?|) branch reset
(?'NAME') named pattern
(?<NAME>) named pattern
(?{code}) code ausfuehren
(??{code}) postponed code
(?(cond)y|n) conditional expression
(?P<NAME>) alias of (?<NAME>)
(?P=NAME) alias of \g{NAME}
(?P>NAME) alias of (?&NAME)
[:alpha:] buchstabe
[:alnum:] ziffer oder buchstabe
[:ascii:] ascii-zeichen
[:blank:] leerzeichen oder tab
[:cntrl:] steuerzeichen
[:digit:] ziffer 0-9
[:graph:]
[:lower:] kleingeschriebener buchstabe
[:print:]
[:punct:]
[:space:] \s oder \v
[:upper:] grossgeschriebener buchstabe
[:word:] buchstabe, ziffer oder unterstrich
[:xdigit:]

[Bearbeiten] Anmerkungen

  1. in der Dokumentation zu Perl 5.12.2 perldoc perlre ist zu lesen:
    "Perl uses the same mechanism to produce $1, $2, etc, so you also pay a price for each pattern that contains capturing parentheses. (To avoid this cost while retaining the grouping behaviour, use the extended regular expression (?: ... ) instead.)"
    Dagegen wird im "Regular Expression HOWTO" Im Python-v2.7-Manual über das Modul re praktisch das Gegenteil gesagt:
    "It should be mentioned that there’s no performance difference in searching between capturing and non-capturing groups; neither form is any faster than the other."[1]
  2. PHP-Manual, PCRE, Abschnitt über Modifiers
  3. Python Manual, Module re
  4. C++ Boost Library - Options for Perl Regular Expressions
  5. Java-Documentation
Meine Werkzeuge
Namensräume

Varianten
Aktionen
Übersicht
Hilfe
SELFHTML
Diverses
Werkzeuge
Flattr
Soziale Netzwerke