Regulaere Ausdruecke
PetaPerl implementiert eine Perl-5-kompatible Regex-Engine mit Unterstuetzung fuer das gesamte Spektrum der Perl-Regex-Funktionalitaeten.
Mustersyntax
Literale
/hello/ # Literales "hello" abgleichen
/foo bar/ # "foo bar" abgleichen
Metazeichen
| Zeichen | Bedeutung |
|---|---|
. | Beliebiges Zeichen ausser Zeilenumbruch |
^ | Anfang der Zeichenkette |
$ | Ende der Zeichenkette |
\A | Anfang der Zeichenkette (absolut) |
\z | Ende der Zeichenkette (absolut) |
\Z | Ende der Zeichenkette oder vor abschliessendem Zeilenumbruch |
\b | Wortgrenze |
\B | Keine Wortgrenze |
\G | Position des letzten Treffers |
/^start/ # Muss am Anfang stehen
/end$/ # Muss am Ende stehen
/\bword\b/ # Ganzes Wort abgleichen
/\Abegin/ # Absoluter Anfang
/finish\z/ # Absolutes Ende
Zeichenklassen
[abc] # a, b oder c abgleichen
[^abc] # Alles ausser a, b, c abgleichen
[a-z] # Kleinbuchstabe abgleichen
[A-Z0-9] # Grossbuchstabe oder Ziffer abgleichen
[a-zA-Z_] # Wortzeichen abgleichen
Vordefinierte Zeichenklassen
| Klasse | Trifft auf | Negiert |
|---|---|---|
\d | Ziffer [0-9] | \D (Nicht-Ziffer) |
\w | Wortzeichen [a-zA-Z0-9_] | \W (Nicht-Wortzeichen) |
\s | Leerraum [ \t\n\r\f] | \S (Nicht-Leerraum) |
\h | Horizontaler Leerraum | \H |
\v | Vertikaler Leerraum | \V |
/\d+/ # Eine oder mehrere Ziffern
/\w+/ # Ein oder mehrere Wortzeichen
/\s*/ # Null oder mehr Leerraum
POSIX-Zeichenklassen
[:alnum:] # Alphanumerisch [a-zA-Z0-9]
[:alpha:] # Alphabetisch [a-zA-Z]
[:ascii:] # ASCII-Zeichen [0-127]
[:blank:] # Leerzeichen und Tabulator
[:cntrl:] # Steuerzeichen
[:digit:] # Ziffern [0-9]
[:graph:] # Sichtbare Zeichen (kein Leerzeichen)
[:lower:] # Kleinbuchstaben
[:print:] # Druckbare Zeichen
[:punct:] # Satzzeichen
[:space:] # Leerraum
[:upper:] # Grossbuchstaben
[:word:] # Wortzeichen [a-zA-Z0-9_]
[:xdigit:] # Hexadezimalziffern [0-9A-Fa-f]
Verwendung: [[:digit:]] oder [[:alpha:][:digit:]]
Quantifizierer
| Quantifizierer | Bedeutung | Gierig | Nicht-gierig | Possessiv |
|---|---|---|---|---|
* | 0 oder mehr | Ja | *? | *+ |
+ | 1 oder mehr | Ja | +? | ++ |
? | 0 oder 1 | Ja | ?? | ?+ |
{n} | Genau n | Ja | N/A | N/A |
{n,} | n oder mehr | Ja | {n,}? | N/A |
{n,m} | n bis m | Ja | {n,m}? | N/A |
/a*/ # 0 oder mehr 'a' (gierig)
/a*?/ # 0 oder mehr 'a' (nicht-gierig)
/a+/ # 1 oder mehr 'a'
/a?/ # 0 oder 1 'a'
/a{3}/ # Genau 3 'a'
/a{3,}/ # 3 oder mehr 'a'
/a{3,5}/ # 3 bis 5 'a'
Gierig vs. nicht-gierig: Gierige Quantifizierer treffen so viel wie moeglich, nicht-gierige treffen so wenig wie moeglich.
# Gegeben: "foo123bar"
/\d+/ # Trifft "123" (gierig)
/\d+?/ # Trifft "1" (nicht-gierig, aber das gesamte Muster muss treffen)
Gruppen und Erfassungen
Erfassungsgruppen
/(foo)/ # "foo" in $1 erfassen
/(foo)(bar)/ # In $1 und $2 erfassen
Zugriff auf Erfassungen ueber $1, $2 usw. oder das @+-Array.
Nicht-erfassende Gruppen
/(?:foo)/ # Gruppieren ohne Erfassung
Verwende diese, wenn Gruppierung noetig ist, aber kein Erfassungsaufwand.
Benannte Erfassungen
/(?<name>\w+)/ # Benannte Erfassung "name"
/(?'name'\w+)/ # Alternative Syntax
Zugriff ueber den $+{name}-Hash.
Alternation
/foo|bar/ # "foo" oder "bar" abgleichen
/(red|green|blue)/ # Farbe erfassen
Anker und Zusicherungen
Zusicherungen mit Nullbreite
| Zusicherung | Bedeutung |
|---|---|
(?=pattern) | Positiver Vorausblick |
(?!pattern) | Negativer Vorausblick |
(?<=pattern) | Positiver Rueckblick |
(?<!pattern) | Negativer Rueckblick |
/foo(?=bar)/ # "foo" gefolgt von "bar" (bar wird nicht verbraucht)
/foo(?!bar)/ # "foo" nicht gefolgt von "bar"
/(?<=foo)bar/ # "bar" dem "foo" vorausgeht
/(?<!foo)bar/ # "bar" dem nicht "foo" vorausgeht
Atomare Gruppen
/(?>pattern)/ # Atomare Gruppe (kein Backtracking)
Einmal getroffen, wird der Inhalt der Gruppe fixiert. Wird zur Leistungsoptimierung verwendet.
Rueckverweise
/(foo)\1/ # Trifft "foofoo" - \1 verweist auf erste Erfassung
/(['"]).*?\1/ # Trifft quotierte Zeichenkette (gleicher Quotierungstyp)
Benannte Rueckverweise
/(?<tag>\w+)...\k<tag>/ # Benannter Rueckverweis
Bedingungen
/(?(condition)yes|no)/ # Wenn Bedingung trifft, versuche "yes", sonst "no"
Bedingungen koennen sein:
- Erfassungsgruppennummer:
(?(1)yes|no)- wenn Gruppe 1 getroffen hat - Benannte Erfassung:
(?(<name>)yes|no)- wenn benannte Gruppe getroffen hat - Vorausblick:
(?(?=test)yes|no)- wenn Vorausblick erfolgreich
Modifizierer
Modifizierer aendern das Verhalten des regulaeren Ausdrucks. Sie werden nach dem schliessenden Begrenzer angegeben:
| Modifizierer | Bedeutung |
|---|---|
i | Gross-/Kleinschreibung ignorieren |
m | Mehrzeilig (^/$ treffen auf Zeilengrenzen) |
s | Einzeilig (. trifft auf Zeilenumbruch) |
x | Erweitert (Leerraum ignorieren, Kommentare erlaubt) |
g | Global (alle Treffer finden) |
c | Suche nach fehlgeschlagenem Abgleich fortsetzen |
o | Einmal kompilieren (veraltet, in PetaPerl nicht noetig) |
e | Ersetzung als Code auswerten (in s///) |
/pattern/i # Gross-/Kleinschreibung ignorieren
/pattern/ms # Mehrzeilig + einzeilig
/pattern/x # Erweitert (lesbar)
/pattern/g # Globaler Abgleich
Beispiele
# Gross-/Kleinschreibung ignorieren
if ($str =~ /hello/i) { ... }
# Mehrzeilig: ^ und $ treffen auf Zeilenanfaenge/-enden
while ($text =~ /^Line: (.+)$/mg) {
print "Gefunden: $1\n";
}
# Erweitert: Leerraum und Kommentare werden ignoriert
my $email_re = qr{
(\w+) # Benutzername
@ # At-Zeichen
([\w.]+) # Domain
}x;
# Global: alle Treffer finden
my @words = $text =~ /\w+/g;
Abgleich und Ersetzung
Abgleichoperator
$str =~ /pattern/ # Wahr wenn Treffer
$str =~ /pattern/g # Global, gibt alle Treffer zurueck
Im Listenkontext mit Erfassungen:
my ($user, $domain) = $email =~ /(\w+)@([\w.]+)/;
Im Listenkontext mit global:
my @numbers = $text =~ /\d+/g; # Alle Zahlen
Ersetzung
$str =~ s/old/new/ # Erstes Vorkommen ersetzen
$str =~ s/old/new/g # Alle Vorkommen ersetzen
$str =~ s/old/new/i # Ersetzen ohne Beachtung der Gross-/Kleinschreibung
$str =~ s/old/new/gi # Global + ohne Beachtung der Gross-/Kleinschreibung
Ersetzung mit Erfassungen:
$str =~ s/(\w+)@(\w+)/$2\@$1/; # user@domain umkehren
Ausgewertete Ersetzung:
$str =~ s/(\d+)/$1 * 2/e; # Alle Zahlen verdoppeln
Transliteration
$str =~ tr/abc/xyz/ # a durch x, b durch y, c durch z ersetzen
$str =~ y/abc/xyz/ # Identisch mit tr
$str =~ tr/a-z/A-Z/ # In Grossbuchstaben umwandeln
$str =~ tr/ //d # Leerzeichen loeschen
$str =~ tr/a-z//c # Nicht-Kleinbuchstaben zaehlen
Spezielle Variablen
Nach einem erfolgreichen Abgleich:
| Variable | Enthaelt |
|---|---|
$& | Gesamte getroffene Zeichenkette |
$` | Zeichenkette vor dem Treffer |
$' | Zeichenkette nach dem Treffer |
$1, $2, … | Erfassungsgruppen |
$+ | Letzte getroffene Erfassung |
@+ | Endpositionen der Erfassungen |
@- | Anfangspositionen der Erfassungen |
%+ | Benannte Erfassungen |
if ($str =~ /(foo)(bar)/) {
print "Gesamttreffer: $&\n"; # "foobar"
print "Gruppe 1: $1\n"; # "foo"
print "Gruppe 2: $2\n"; # "bar"
print "Davor: $`\n";
print "Danach: $'\n";
}
Regex-Kompilierung
qr//-Operator
Regulaeren Ausdruck zur Wiederverwendung kompilieren:
my $word = qr/\w+/;
my $email = qr/\w+@\w+\.\w+/;
if ($str =~ $word) { ... }
if ($str =~ /$word@$word/) { ... } # Interpolieren
Vorteile:
- Einmal kompilieren, vielfach verwenden
- Lesbare Regex-Komposition
- Leistungsoptimierung
Leistungsueberlegungen
Verankerte Muster
Mit ^ oder \A verankerte Muster sind schneller:
/^pattern/ # Schnell: prueft nur den Anfang
/pattern/ # Langsamer: durchsucht die gesamte Zeichenkette
Atomare Gruppen
Verwende atomare Gruppen (?>...) um Backtracking zu verhindern:
# Langsam: Backtracking bei Fehlschlag
/\d+\w+/
# Schnell: kein Backtracking in \d+
/(?>\d+)\w+/
Nicht-erfassende Gruppen
Verwende (?:...) wenn Erfassungen nicht benoetigt werden:
/(?:foo|bar)/ # Schneller als /(foo|bar)/ wenn Erfassung nicht noetig
PetaPerl-spezifische Funktionalitaeten
Bytecode-Kompilierung
Regex-Muster werden zu Bytecode kompiliert fuer effiziente Ausfuehrung. PetaPerl verwendet:
- Bitmap-Zeichenklassen fuer schnellen ASCII-Abgleich
- Literal-Praefix-Extraktion zum Ueberspringen unmoeglicher Positionen
- Ankerungserkennung zur Vermeidung unnuetzen Durchsuchens
Possessive Quantifizierer
Possessive Quantifizierer verhindern Backtracking vollstaendig (effizienter als atomare Gruppen fuer einfache Faelle):
/a++/ # 1 oder mehr 'a', kein Backtracking
/a*+/ # 0 oder mehr 'a', kein Backtracking
/a?+/ # 0 oder 1 'a', kein Backtracking
Eingebetteter Code
/pattern(?{ code })/ # Code waehrend des Abgleichs ausfuehren
/(??{ code })/ # Verzoegerter Regex (Code gibt Muster zurueck)
(?{code}) fuehrt Perl-Code an der Stelle im Muster aus, an der er erscheint. Der Code kann auf $1, $2 usw. aus bisherigen Erfassungen zugreifen.
Aktuelle Einschraenkungen
PetaPerls Regex-Engine besteht 99,3% der re_tests-Testsuite von perl5 (1959/1972 Tests). Verbleibende Luecken:
- Selbstreferenzierende Erfassungen – Muster wie
(a\1)(3 Tests) localin Codebloecken –(?{ local $x = ... })(2 Tests)- Mehrzeichenfaltung bei Gross-/Kleinschreibung – Unicode-Zeichen, die zu mehreren Zeichen gefaltet werden (2 Tests)
- Branch-Reset-Rueckverweise – komplexe
(?|...)-Muster mit Rueckverweisen (5 Tests) - Randfaelle bei Zeichenketteninterpolation – 1 Test
Unicode-Eigenschaftsunterstuetzung (\p{Letter}, \p{Digit} usw.) ist vollstaendig implementiert fuer standardmaessige Unicode-Kategorien.
Beispiele
E-Mail-Validierung
my $email_re = qr/^[\w.+-]+@[\w.-]+\.[a-zA-Z]{2,}$/;
if ($email =~ $email_re) {
print "Gueltige E-Mail\n";
}
URL-Analyse
my ($protocol, $host, $path) = $url =~
m{^(https?)://([^/]+)(/.*)$};
Protokolldatei-Analyse
while ($line =~ /\[(\d{4}-\d{2}-\d{2})\] (\w+): (.+)/g) {
my ($date, $level, $msg) = ($1, $2, $3);
# Protokolleintrag verarbeiten
}
Zeichenkettenbereinigung
# Mehrfache Leerzeichen entfernen
$text =~ s/\s+/ /g;
# Fuehrenden/nachfolgenden Leerraum entfernen
$text =~ s/^\s+|\s+$//g;
# Oder mit zwei Ersetzungen
$text =~ s/^\s+//;
$text =~ s/\s+$//;
Vorlagenersetzung
my %vars = (name => "John", age => 30);
my $template = "Hallo {{name}}, du bist {{age}} Jahre alt.";
$template =~ s/\{\{(\w+)\}\}/$vars{$1}/ge;