| perlrequick Dokumentation zu Perl 5.9.2 | Download als POD | Wie kann ich hier etwas ändern? |
"Hallo Welt" =~ /Welt/; # passt
In diesem Ausdruck ist Welt die Regex und das // im umschlossenen /Welt/ sagt perl, dass es einen String nach einem Treffer durchsuchen soll. Der Operator =~ verbindet den String mit der Regexsuche und liefert einen wahren Wert, wenn die Regex passt, oder falsch, wenn die Regex nicht passt. In unserem Fall passt Welt auf das zweite Wort in "Hallo Welt" , daher ist der Ausdruck wahr. Zu diesem Konzept gibt es verschiedene Variationen.
Ausdrücke wie dieser sind nützlich in Bedingungen:
print "Es passt\n" if "Hallo Welt" =~ /Welt/;
Die Aussage des Matches kann durch den Operator !~ umgekehrt werden:
print "Es passt nicht\n" if "Hallo Welt" !~ /Welt/;
Die literale Zeichenkette in der Regex kann durch eine Variable ersetzt werden:
$gruss = "Welt";
print "Es passt\n" if "Hallo Welt" =~ /$gruss/;
Wenn man $_ prüft, kann der Teil $_ =~ weggelassen werden:
$_ = "Hallo Welt";
print "Es passt\n" if /Welt/;
Schließlich kann man noch die Standardbegrenzer // durch beliebige andere ersetzen, wenn man ein 'm' davor setzt:
"Hallo Welt" =~ m!Welt!; # passt, begrenzt durch '!'
"Hallo Welt" =~ m{Welt}; # passt, man beachte die passenden '{}'
"/usr/bin/perl" =~ m"/perl"; # passt hinter '/usr/bin',
# '/' wird zu einem normalen Zeichen
Eine Regex muss exakt auf einen Teil des Strings passen, damit der Ausdruck wahr wird:
"Hallo Welt" =~ /welt/; # passt nicht, Klein- statt Großschreibung
"Hallo Welt" =~ /o W/; # passt, ' ' ist ein normales Zeichen
"Hallo Welt" =~ /Welt /; # passt nicht, kein ' ' am Ende
perl wird immer den erstmöglichen Treffer im String finden:
"Hallo Welt" =~ /l/; # passt auf das erste 'l' in 'Hallo'
"Dieses Brot ist rot" =~ /rot/; # passt auf das 'rot' in 'Brot'
In einer Regex können nicht alle Zeichen benutzt werden 'wie sie sind'. Einige Zeichen, so genannte Metazeichen , sind für die Regex-Syntax reserviert. Diese Metazeichen sind
{}[]()^$.|*+?\
Nach einem Metazeichen kann man suchen, indem man ein Backslash davor setzt:
"2+2=4" =~ /2+2/; # passt nicht, '+' ist ein Metazeichen
"2+2=4" =~ /2\+2/; # passt, \+ wird wie ein einfaches '+' gefunden
'C:\WIN32' =~ /C:\\WIN/; # passt
"/usr/bin/perl" =~ /\/usr\/bin\/perl/; # passt
In der letzten Regex steht auf vor dem normalen Schrägstrich '/' ein Backslash, weil er auch benutzt wird, um die Regex zu begrenzen.
Nicht-druckbare ASCII-Zeichen werden durch Escape-Sequenzen dargestellt. Übliche Beispiele sind \t für Tab, \n für ein Newline und \r für einen Wagenrücklauf ("carriage return"). Beliebige Bytes werden durch eine oktale Escape-Sequenz, wie in \033 , oder durch eine hexadezimale Escape-Sequenz, wie in \x1B , beschrieben:
"1000\t2000" =~ m(0\t2) # passt
"Hut" =~ /\110\x75\x74/ # passt, ist aber eine merkwürdige
# Art, 'Hut' zu buchstabieren
Regexen werden im Wesentlichen wie Zeichenketten in doppelten Anführungszeichen behandelt, daher funktioniert Variablenersetzung:
$foo = 'haus';
'katzenhaus' =~ /katzen$foo/; # passt
'hauskatzen' =~ /${foo}katzen/; # passt
Bei allen bisherigen Regexen hatte man einen Treffer, wenn die Regex irgendwo im String passte. Um genau festzulegen, wo sie passen soll, können wir die Anker -Metazeichen ^ und $ benutzen. Das Ankerzeichen ^ steht für einen Treffer am Anfang des Strings, und das Ankerzeichen $ steht für einen Treffer am Ende des Strings oder direkt vor einem Newline am Ende des Strings. Ein paar Beispiele:
"haushalt" =~ /halt/; # passt
"haushalt" =~ /^halt/; # passt nicht
"haushalt" =~ /halt$/; # passt
"haushalt\n" =~ /halt$/; # passt
"haushalt" =~ /^haushalt$/; # passt
[...] gekennzeichnet, zwischen denen die Menge der möglichen Zeichen steht. Hier sind ein paar Beispiele:
/bett/; # passt auf 'bett'
/[bnf]ett/; # passt auf 'bett', 'nett' oder 'fett'
"abc" =~ /[cab]/; # passt auf 'a'
Beim letzten Beispiel ist zwar 'c' das erste Zeichen in der Zeichenklasse, aber der früheste Punkt, an dem die Regex passen kann, ist das das 'a' .
/[jJ][aA]/; # passt auf 'ja' ohne Berücksichtigung von Groß-
# und Kleinschreibung: 'ja', 'JA', 'Ja' oder 'jA'
/ja/i; # passt auch auf 'ja', 'JA', 'Ja' oder 'jA'
Das letzte Beispiel zeigt einen Treffer mit dem Modifier 'i' , der dafür sorgt, dass bei der Suche die Groß-/Kleinschreibung ignoriert wird.
Auch Zeichenklassen kennen gewöhnliche und besondere Zeichen, aber es sind innerhalb der Zeichenklasse andere als außerhalb. Die besonderen Zeichen für Zeichenklassen sind -]\^$ . Man kann nach ihnen suchen, indem man ihnen ein \ als Escapezeichen vorsetzt:
/[\]c]def/; # passt auf ']def' oder 'cdef' $x = 'bcr'; /[$x]at/; # passt auf 'bat, 'cat' oder 'rat' /[\$x]at/; # passt auf '$at' oder 'xat' /[\\$x]at/; # passt auf '\at', 'bat, 'cat' oder 'rat'Das spezielle Zeichen
'-' dient innerhalb einer Zeichnklasse als Bereichsoperator, so dass aus den unhandlichen Ausdrücken [0123456789] und [abc...xyz] die anmutigeren Lösungen [0-9] und [a-z] werden:
/teil[0-9]/; # passt auf 'teil0' oder 'teil1' oder ... oder 'teil9'
/[0-9a-fA-F]/; # passt auf eine hexadezimale Ziffer
Wenn '-' erstes oder letztes Zeichen in einer Zeichenklasse ist, wird es als normales Zeichen behandelt.
Das spezielle Zeichen '^' an der ersten Stelle in einer Zeichenklasse kennzeichnet eine negierte Zeichenklasse , die auf alle Zeichen außer denen in eckigen Klammern passt. Sowohl [...] also auch [^...] müssen auf ein Zeichen passen, oder der Match schlägt fehl.
/[^a]at/; # passt nicht auf 'aat' oder 'at', aber passt auf
# 'bat', 'cat, '0at', '%at', u.s.w.
/[^0-9]/; # passt auf ein nicht-numerisches Zeichen
/[a^]at/; # passt auf 'aat' oder '^at'; hier hat das '^'
# keine besondere Bedeutung
In Perl gibt es einige Abkürzungen für häufiger benutzte Zeichenklassen:
\d ist eine Ziffer und steht für
[0-9]
\s ist ein Whitespace-Zeichen und steht für
[\ \t\r\n\f]
\w ist ein Wortzeichen (alphanumerisch oder _) und steht für
[0-9a-zA-Z_]
\D ist ein negiertes \d; es steht für ein beliebiges Zeichen, das keine Ziffer ist.
[^0-9]
\S ist ein negiertes \s; es steht für ein beliebiges Nicht-Whitespace-Zeichen.
[^\s]
\W ist ein negiertes \w; es steht für ein beliebiges Nicht-Wortzeichen.
[^\w]
Der Punkt '.' passt auf jedes Zeichen außer "\n".
\d\s\w\D\S\W können sowohl innerhalb wie auch außerhalb von Zeichenklassen genutzt werden. Hier ein paar Beispiele:
/\d\d:\d\d:\d\d/; # passt auf ein hh:mm:ss Zeitformat
/[\d\s]/; # passt auf Ziffer oder Whitespace-Zeichen
/\w\W\w/; # passt auf ein Wortzeichen, gefolgt von einem
# Nicht-Wortzeichen, gefolgt von einem Wortzeichen
/..rt/; # passt auf zwei beliebige Zeichen, gefolgt von 'rt'
/ende\./; # passt auf 'ende.'
/ende[.]/; # gleiche Bedeutung, passt auf 'ende.'
Der Wortanker \b passt auf die Grenze zwischen einem Wort- und einem Nicht-Wortzeichen, also \w\W oder \W\w :
$x = "Wer Strandgut immer gutwillig einsammelt, der verdient gut.";
$x =~ /\bgut/; # passt auf 'gut' in 'gutwillig'
$x =~ /gut\b/; # passt auf 'gut' in 'Strandgut'
$x =~ /\bgut\b/; # passt auf 'gut' am Ende des Strings
Beim letzten Beispiel wird das Ende des Strings als Wortgrenze genommen.
'|' für Alternation kann man auch nach verschiedenen Strings suchen. Um Nach Hund oder Katze zu suchen, bilden wir die Regex Hund|Katze . Wie zuvor versucht perl, die Regex an der frühest möglichen Stelle im String zu finden. An jeder Zeichenposition wird perl zuerst versuchen, die erste Alternative, Hund , zu matchen. Wenn Hund nicht passt, versucht perl die nächste Alternative, Katze . Wenn Katze auch nicht passt, misslingt der Match und perl geht weiter zur nächsten Position im String. Ein paar Beispiele:
"Katzen und Hunde" =~ /Katze|Hund|Vogel/; # passt auf "Katze"
"Katzen und Hunde" =~ /Hund|Katze|Vogel/; # passt auf "Katze"
Obwohl in der zweiten Regex Hund die erste Alternative ist, wird Katze früher im String gefunden.
"Katzen" =~ /K|Ka|Kat|Katz|Katze|Katzen/; # passt auf "K"
"Katzen" =~ /Katzen|Katze|Katz|Kat|Ka|K/; # passt auf "Katzen"
An einer gegebenen Zeichenposition gewinnt diejenige Alternative, die zuerst dafür sorgt, dass die Regex passt. In diesem Fall passen alle Alternativon schon an der ersten Zeichenposition, daher gewinnt jeweils der erste Match.
() zum Gruppieren erlauben es, einen Teil einer Regex als eine Einheit zu betrachten. Teile einer Regex werden gruppiert, indem man sie in runden Klammern einschließt. Die Regex Haus(katze|halt) bedeutet "suche Haus gefolgt entweder von katze oder halt ". Hier ein paar weitere Beispiele:
/(a|b)b/; # passt auf 'ab' oder 'bb'
/(^a|b)c/; # passt auf 'ac' am Anfang eines Strings
# oder 'bc' irgendwo
/Haus(katze|)/; # passt auf 'Hauskatze' oder 'Haus'
/Haus(katze(n|)|)/; # passt entweder auf 'Hauskatzen' oder
# 'Hauskatze' oder 'Haus'.
# Merke: Klammern können geschachtelt werden.
"20" =~ /(19|20|)\d\d/; # passt auf die Leer-Alternative '()\d\d',
# da '20\d\d' nicht passen kann.
() erlauben es auch, aus einem String einen Teil, der gefunden wurde, zu extrahieren. Für jede Gruppe landet der gefundene Teil in den Spezialvariablen $1 , $2 und so weiter. Sie können wir normale Variablen benutzt werden:
# Stunden, Minuten und Sekunden extrahieren
$zeit =~ /(\d\d):(\d\d):(\d\d)/; # passt auf das Format hh:mm:ss
$stunden = $1;
$minuten = $2;
$sekunden = $3;
Im Listenkontext liefert ein Match /regex/ mit Gruppierungen die Liste der gefundenen Werte ($1,$2,...) zurück. Also können wir das umschreiben als
($stunden, $minuten, $sekunden) = ($time =~ /(\d\d):(\d\d):(\d\d)/);
Wenn die Gruppierungen in einer Regex verschachtelt sind, landet die Gruppe mit der am weitesten links stehenden öffnenden Klammer in $1 , die nächste öffnende Klammer in $2 und so weiter. Hier ein Beispiel für eine komplexe Regex mit den zugehörigen Variablennummern darunter:
/(ab(cd|ef)((gi)|j))/;
1 2 34
Verknüpft mit den Match-Variablen $1 , $2 , ... sind die Rückreferenzen (engl. backreferences ) \1 , \2 , ... Rückreferenzen sind Treffervariablen, die innerhalb einer Regex genutzt werden können:
/(\w\w\w)\s\1/; # Finde Folgen der Art 'das das' im String
$1 , $2 , ... sollten nur außerhalb und \1 , \2 , ... nur innerhalb einer Regex genutzt werden.
? , * , + und {} erlauben uns, die Anzahl der Wiederholungen für einen Teil einer Regex zu bestimmen, die wir suchen. Die Quantifikatoren werden direkt hinter das Zeichen, die Zeichenklasse oder die Gruppierung gesetzt, die wir bezeichnen wollen. Sie haben die folgenden Bedeutungen:
a? = 1 oder 0 mal 'a'
a* = 0 or mehr Male 'a', d.h. beliebig oft
a+ = 1 or mehr Male 'a', d.h. mindestens einmal
a{n,m} = mindestens n mal 'a', aber nicht mehr als m mal.
a{n,} = mindestens n oder mehr Male 'a'
a{n} = genau n mal 'a'
/[a-z]+\s+\d*/; # passt auf ein kleingeschriebenes Wort, mindestens
# ein Whitespace und eine beliebige Folge von Ziffern
/(\w+)\s+\1/; # passt auf verdoppelte Wörter mit beliebiger Länge
$jahr =~ /\d{2,4}/; # stellt sicher, dass $jahr mindestens 2 aber
# nicht mehr als 4 Ziffern hat
$jahr =~ /\d{4}|\d{2}/; # Besserer Match, wirft Jahre mit 3 Ziffern
# heraus
Diese Quantifizierer versuchen, einen möglichst langen Teil des Strings zu matchen, auf den immer noch die Regex passt. So bekommen wir
$x = 'Die Katze auf Matratze';
$x =~ /^(.*)(atze)(.*)$/; # ergibt folgende Treffer:
# $1 = 'Die Katze auf der Matr';
# $2 = 'atze';
# $3 = ''; (leerer Treffer)
Der erste Quantifizierer .* schnappt sich so viel wie möglich vom String, sodass die Regex immer noch passt. Für den zweiten Quantifizierer .* bleiben keine Zeichen mehr übrig, also bleibt ein leerer String.
$muster = 'Hoffmann';
while (<>) {
print if /$muster/;
}
muss perl bei jedem Schleifendurchlauf $muster neu auswerten. Wenn sich $pattern nicht ändert, benutzen Sie den Modifier //o , um die Variablenersetzung nur einmal vorzunehmen. Wenn Sie gar keine Ersetzung möchten, benutzen Sie die speziellen Begrenzer m'' :
@muster = ('Hoffmann');
m/@muster/; # findet 'Hoffmann'
m'@muster'; # findet die Zeichenkette '@muster'
Mit dem Modifier //g (für "global") findet eine Suche in einem String beliebig oft statt. In einem skalaren Kontext springt //g bei aufeinander folgenden Aufrufen von Treffer zu Treffer und merkt sich dabei jedes Mal die Position im String. Man kann diese Position mit der Funktion pos() auslesen oder setzen. Das folgende Beispiel
$x = "Katze Hund Haus"; # 3 Wörter
while ($x =~ /(\w+)/g) {
print "Wort ist $1, endet an Position ", pos $x, "\n";
}
ergibt diese Ausgabe:
Wort ist Katze, endet an Position 5
Wort ist Hund, endet an Position 10
Wort ist Haus, endet an Position 15
Wenn die Suche fehlschlägt oder sich der Zielstring ändert, wird die Position zurückgesetzt. Wenn man nicht möchte, dass die Position nach einer fehlgeschlagenen Suche zurückgesetzt wird, muss man noch den Modifier //c benutzen, also /regex/gc .
Im Listenkontext liefert //g eine Liste der gefundenen Gruppierungen zurück. Wenn es keine Gruppierungen gibt, wird eine Liste der Treffer der ganzen Regex zurückgeliefert.
@worte = ($x =~ /(\w+)/g); # passt,
# $worte[0] = 'Katze'
# $worte[1] = 'Hund'
# $worte[2] = 'Haus'
s/regex/ersetzung/modifier kann man suchen und ersetzen. Dabei entspricht ersetzung einer Perl-Zeichenkette in doppelten Anführungszeichen und ersetzt im String das, was auf regex passt. Auch hier wird der Operator =~ benutzt, um den String mit der regex zu verknüpfen. Wenn die Suche in $_ erfolgt, kann das $_ =~ weggelassen werden. Wenn es einen Treffer gibt, liefert s/// die Anzahl der Ersetzungen zurück, andernfalls ein false. Hier ein paar Beispiele:
$x = "Zeit, den Hund zu füttern!";
$x =~ s/Hund/Hacker/; # $x enthält "Zeit, den Hacker zu füttern!"
$y = "'gequotete Worte'";
$y =~ s/^'(.*)'$/$1/; # einfache Anführungszeichen entfernen
# $y enthält "gequotete Worte"
Beim Operator s/// können die Treffer-Variablen $1 , $2 u.s.w. sofort im Ersetzungsausdruck verwendet werden. Zusammen mit dem Global-Modifier als s///g kann man alle Vorkommen der Regex im String auf einmal ersetzen:
$x = "Das Zimmer hat 3 mal 3 Meter";
$x =~ s/3/drei/; # $x enthält "Das Zimmer hat drei mal 3 Meter";
$x = "Das Zimmer hat 3 mal 3 Meter";
$x =~ s/3/drei/g; # $x enthält "Das Zimmer hat drei mal drei Meter";
Der Evaluierungs-Modifier s///e packt ein eval{...} um den Ersetzungsteil, und das evaluierte Ergebnis ist die Ersetzung für die gefundene Teilzeichenkette. Ein paar Beispiele:
# Jedes Wort in einem String umdrehen
$x = "Das Haus auf dem Land.";
$x =~ s/(\w+)/reverse $1/ge; # $x enthält "saD suaH fua med dnaL."
# Prozente in Dezimalbruch umwandeln
$x = "Eine Trefferquote von 39%";
$x =~ s!(\d+)%!$1/100!e; # $x enthält "Eine Trefferquote von 0.39"
Das zweite Beispiel zeigt auch, dass man bei s/// andere Begrenzer einsetzen kann, wie zum Beispiel s!!! oder s{}{} oder sogar s{}// . Wenn einfache Anführungszeichen benutzt werden s''' , dann werden Regex und Ersetzung wie einfach gequotete Strings behandelt.
split /Regex/, String wird der String in eine Liste von Teilstrings aufgeteilt und die sich ergebende Liste zurückgeliefert. Die Regex bestimmt dabei die Zeichenfolge, an der der String aufgeteilt wird. Man kann so zum Beispiel einen String in Worte aufteilen:
$x = "Calvin und Hobbes";
@worte = split /\s+/, $x; # $worte[0] = 'Calvin'
# $worte[1] = 'und'
# $worte[2] = 'Hobbes'
So kann man eine durch Kommata getrennte Liste von Zahlen (mit Dezimalpunkt) aufteilen:
$x = "1.618,2.718, 3.142";
@konst = split /,\s*/, $x; # $konst[0] = '1.618'
# $konst[1] = '2.718'
# $konst[2] = '3.142'
Verwendet man die leere Regex // , dann wird der String in einzelne Zeichen aufgeteilt. Wenn in der Regex Gruppierungen vorkommen, dann enthält die erzeugte Liste auch die gefundenen Teilzeichenkette aus den Gruppierungen:
$x = "/usr/bin";
@teile = split m!(/)!, $x; # $teile[0] = ''
# $teile[1] = '/'
# $teile[2] = 'usr'
# $teile[3] = '/'
# $teile[4] = 'bin'
Weil das erste Zeichen von $x auf die Regex passte, hängt split noch ein leeres Element vor die Liste.
| I | Attachment | Action | Size | Date | Who | Comment |
|---|---|---|---|---|---|---|
| |
perlrequick-5.9.2.pod | manage | 19.3 K | 2009-09-15 - 23:01 | HaraldBongartz | deutsche Version von perlrequick zu Perl 5.9.2 |