GoGPT Best VPN GoSearch

OnWorks-Favicon

perlretut - Online in der Cloud

Führen Sie perlretut im kostenlosen Hosting-Anbieter OnWorks über Ubuntu Online, Fedora Online, Windows Online-Emulator oder MAC OS Online-Emulator aus

Dies ist der Befehl perlretut, der im kostenlosen Hosting-Anbieter OnWorks mit einer unserer zahlreichen kostenlosen Online-Workstations wie Ubuntu Online, Fedora Online, Windows Online-Emulator oder MAC OS Online-Emulator ausgeführt werden kann.

PROGRAMM:

NAME/FUNKTION


perlretut - Tutorial zu regulären Ausdrücken in Perl

BESCHREIBUNG


Auf dieser Seite finden Sie ein grundlegendes Tutorial zum Verstehen, Erstellen und Verwenden von regulären
Ausdrücke in Perl. Es dient als Ergänzung zur Referenzseite über reguläre
Ausdrücke perlre. Reguläre Ausdrücke sind ein integraler Bestandteil der "m//", "s///", "qr//"
und "Split"-Operatoren und so überschneidet sich dieses Tutorial auch mit "Regexp Quote-Like
Operatoren" in Perlop und "Split" in Perlfunc.

Perl ist weithin bekannt für seine hervorragende Textverarbeitung, und reguläre Ausdrücke sind einer
einer der Hauptgründe für diesen Ruhm. Reguläre Ausdrücke in Perl weisen eine Effizienz und
Flexibilität, die in den meisten anderen Computersprachen unbekannt ist. Selbst die Beherrschung der Grundlagen von
Mithilfe regulärer Ausdrücke können Sie Text überraschend einfach bearbeiten.

Was ist ein regulärer Ausdruck? Ein regulärer Ausdruck ist einfach eine Zeichenfolge, die eine
Muster. Muster sind heutzutage weit verbreitet; Beispiele sind die Muster, die in ein
Suchmaschine zum Auffinden von Webseiten und die Muster, die zum Auflisten von Dateien in einem Verzeichnis verwendet werden, z. B.
"ls *.txt" oder "dir *.*". In Perl werden die durch reguläre Ausdrücke beschriebenen Muster verwendet
um Zeichenfolgen zu suchen, gewünschte Teile von Zeichenfolgen zu extrahieren und Suchen und Ersetzen durchzuführen
Operationen.

Reguläre Ausdrücke haben den unverdienten Ruf, abstrakt und schwer zu
verstehen. Reguläre Ausdrücke werden mit einfachen Konzepten wie Konditionalen konstruiert
und Schleifen und sind nicht schwieriger zu verstehen als die entsprechenden "if"-Bedingungen
und "while"-Schleifen in der Perl-Sprache selbst. Tatsächlich ist die größte Herausforderung beim Lernen
regulären Ausdrücken ist nur die Gewöhnung an die knappe Notation, die verwendet wird, um diese auszudrücken
Konzepte.

Dieses Tutorial vereinfacht die Lernkurve, indem es Konzepte regulärer Ausdrücke erläutert, zusammen mit
mit ihrer Notation, einzeln und mit vielen Beispielen. Der erste Teil des Tutorials
Sie werden von den einfachsten Wortsuchen zu den grundlegenden Konzepten regulärer Ausdrücke fortschreiten.
Wenn Sie den ersten Teil beherrschen, verfügen Sie über alle Werkzeuge, die Sie benötigen, um etwa 98 % der
Ihre Bedürfnisse. Der zweite Teil des Tutorials ist für diejenigen, die mit den Grundlagen vertraut sind und
hungrig nach mehr Power-Tools. Es diskutiert die fortgeschritteneren regulären Ausdrucksoperatoren
und stellt die neuesten Spitzeninnovationen vor.

Hinweis: Um Zeit zu sparen, wird „regulärer Ausdruck“ häufig als „regexp“ oder „regex“ abgekürzt.
Regexp ist eine natürlichere Abkürzung als Regex, aber schwieriger auszusprechen. Die Perl
Die Pod-Dokumentation ist gleichmäßig auf Regexp vs. Regex aufgeteilt; in Perl gibt es mehr als einen Weg
um es abzukürzen. Wir werden in diesem Tutorial reguläre Ausdrücke verwenden.

Neu in v5.22, "use re 'strict'" wendet beim Kompilieren strengere Regeln an als sonst.
Muster für reguläre Ausdrücke. Es kann Dinge finden, die zwar legal sind, aber möglicherweise nicht das sind, was Sie tun
beabsichtigt.

Teil 1: Die Grundlagen


Einfacher Wort Abstimmung
Der einfachste reguläre Ausdruck ist einfach ein Wort oder allgemeiner eine Zeichenfolge. Ein regulärer Ausdruck
bestehend aus einem Wort stimmt mit jeder Zeichenfolge überein, die dieses Wort enthält:

"Hallo Welt" =~ /Welt/; # Streichhölzer

Worum geht es bei dieser Perl-Anweisung? „Hello World“ ist eine einfache Zeichenfolge in doppelten Anführungszeichen.
"World" ist der reguläre Ausdruck und das "//" umschließende "/World/" weist Perl an, nach einem
Zeichenfolge für eine Übereinstimmung. Der Operator "=~" verknüpft die Zeichenfolge mit der Regexp-Übereinstimmung und
erzeugt einen wahren Wert, wenn der reguläre Ausdruck übereinstimmt, oder einen falschen, wenn der reguläre Ausdruck nicht übereinstimmt. In unserem
In diesem Fall entspricht „World“ dem zweiten Wort in „Hello World“, also ist der Ausdruck wahr.
Ausdrücke wie dieser sind in Bedingungen nützlich:

if ("Hallo Welt" =~ /Welt/) {
print "Es passt\n";
}
else {
print "Es passt nicht\n";
}

Es gibt nützliche Variationen zu diesem Thema. Der Sinn der Übereinstimmung kann umgekehrt werden durch
mit dem Operator "!~":

if ("Hallo Welt" !~ /Welt/) {
print "Es passt nicht\n";
}
else {
print "Es passt\n";
}

Die Literalzeichenfolge im regulären Ausdruck kann durch eine Variable ersetzt werden:

$gruß = "Welt";
if ("Hallo Welt" =~ /$greeting/) {
print "Es passt\n";
}
else {
print "Es passt nicht\n";
}

Wenn Sie mit der speziellen Standardvariable $_ vergleichen, kann der Teil "$_ =~"
weggelassen:

$_ = "Hallo Welt";
if (/Welt/) {
print "Es passt\n";
}
else {
print "Es passt nicht\n";
}

Und schließlich können die "//" Standardtrennzeichen für eine Übereinstimmung in beliebige geändert werden
Trennzeichen durch ein vorangestelltes „m“:

"Hallo Welt" =~ m!Welt!; # Übereinstimmungen, getrennt durch '!'
"Hallo Welt" =~ m{Welt}; # Übereinstimmungen, beachten Sie das übereinstimmende '{}'
"/ Usr / bin / perl" =~ m"/perl"; # entspricht nach '/ usr / bin',
# '/' wird zu einem gewöhnlichen Zeichen

"/World/", "m!World!" und "m{World}" repräsentieren alle dasselbe. Wenn beispielsweise das Zitat
(""") wird als Trennzeichen verwendet, der Schrägstrich '/' wird zu einem normalen Zeichen und kann
kann in diesem regulären Ausdruck problemlos verwendet werden.

Betrachten wir, wie verschiedene reguläre Ausdrücke mit „Hallo Welt“ übereinstimmen würden:

"Hallo Welt" =~ /Welt/; # stimmt nicht überein
"Hallo Welt" =~ /o W/; # Übereinstimmungen
"Hallo Welt" =~ /oW/; # stimmt nicht überein
"Hallo Welt" =~ /Welt /; # stimmt nicht überein

Der erste reguläre Ausdruck "world" stimmt nicht überein, da reguläre Ausdrücke zwischen Groß- und Kleinschreibung unterscheiden. Der zweite
Der reguläre Ausdruck stimmt überein, weil die Teilzeichenfolge 'o W' in der Zeichenfolge "Hello World" vorkommt. Das Leerzeichen
Das Zeichen „ “ wird wie jedes andere Zeichen in einem regulären Ausdruck behandelt und muss in
in diesem Fall. Das Fehlen eines Leerzeichens ist der Grund, warum der dritte reguläre Ausdruck 'oW' nicht
Übereinstimmung. Der vierte reguläre Ausdruck 'Welt' stimmt nicht überein, da am Ende ein Leerzeichen steht.
der reguläre Ausdruck, aber nicht am Ende der Zeichenfolge. Die Lektion hier ist, dass reguläre Ausdrücke übereinstimmen müssen
ein Teil der Saite genau damit die Aussage wahr ist.

Wenn ein regulärer Ausdruck an mehr als einer Stelle in der Zeichenfolge übereinstimmt, findet Perl immer an der
frühestmöglicher Punkt in der Zeichenfolge:

"Hallo Welt" =~ /o/; # stimmt mit 'o' in 'Hallo' überein
"Der Hut ist rot" =~ /Hut/; # stimmt mit 'Hut' in 'Das' überein

In Bezug auf die Zeichenübereinstimmung gibt es noch einige weitere Punkte, die Sie wissen sollten.
Erstens können nicht alle Zeichen unverändert in einer Übereinstimmung verwendet werden. Einige Zeichen, genannt
Metazeichensind für die Verwendung in der Regexp-Notation reserviert. Die Metazeichen sind

{}[]()^$.|*+?\

Die Bedeutung jedes dieser Punkte wird im weiteren Verlauf des Tutorials erläutert, aber für
Jetzt ist es nur wichtig zu wissen, dass ein Metazeichen durch das Einfügen eines
Backslash davor:

"2+2=4" =~ /2+2/; # stimmt nicht überein, + ist ein Metazeichen
"2+2=4" =~ /2\+2/; # trifft zu, \+ wird wie ein gewöhnliches + . behandelt
"Das Intervall ist [0,1)." =~ /[0,1)./ # ist ein Syntaxfehler!
"Das Intervall ist [0,1)." =~ /\[0,1\)\./ # Übereinstimmungen
"#!/ Usr / bin / perl" =~ /#!\/ usr\/Behälter\/perl/; # Streichhölzer

Im letzten regulären Ausdruck wird der Schrägstrich '/' auch als Backslash verwendet, da er dazu dient,
begrenzen den regulären Ausdruck. Dies kann jedoch zu LTS (Leaning Toothpick Syndrome) führen, und es ist
oft ist es lesbarer, Trennzeichen zu ändern.

"#!/ Usr / bin / perl" =~ m!#\!/ Usr / bin / perl!; # leichter zu lesen

Das Backslash-Zeichen „\“ ist selbst ein Metazeichen und muss mit einem Backslash versehen werden:

'C:\WIN32' =~ /C:\\WIN/; # Streichhölzer

Zusätzlich zu den Metazeichen gibt es einige ASCII-Zeichen, die nicht
druckbare Zeichenäquivalente und werden stattdessen dargestellt durch Flucht Sequenzen. Verbreitet
Beispiele sind "\t" für einen Tabulator, "\n" für einen Zeilenumbruch, "\r" für einen Wagenrücklauf und "\a" für eine
Glocke (oder Alarm). Wenn Sie Ihren String besser als eine Folge beliebiger Bytes betrachten,
die oktale Escape-Sequenz, z. B. "\033", oder die hexadezimale Escape-Sequenz, z. B. "\x1B", kann
eine natürlichere Darstellung für Ihre Bytes sein. Hier sind einige Beispiele für Escapezeichen:

"1000\t2000" =~ m(0\t2) # Übereinstimmungen
"1000\n2000" =~ /0\n20/ # Übereinstimmungen
"1000\t2000" =~ /\000\t2/ # passt nicht, "0" ne "\000"
"cat" =~ /\o{143}\x61\x74/ # entspricht ASCII, aber auf eine seltsame Art und Weise
# um Katze zu buchstabieren

Wenn Sie sich schon eine Weile mit Perl auskennen, kommt Ihnen das ganze Gerede über Escape-Sequenzen vielleicht bekannt vor.
Ähnliche Escape-Sequenzen werden in doppelten Anführungszeichen verwendet und tatsächlich die regulären Ausdrücke in Perl
werden meist als doppelte Anführungszeichen behandelt. Das bedeutet, dass Variablen in
Regexps auch. Genau wie doppelte Anführungszeichen Strings, die Werte der Variablen in der
Der reguläre Ausdruck wird ersetzt, bevor der reguläre Ausdruck für Übereinstimmungszwecke ausgewertet wird. Wir
haben:

$foo = 'Haus';
'housecat' =~ /$foo/; # Übereinstimmungen
'Katzenhaus' =~ /cat$foo/; # Streichhölzer
'Hauskatze' =~ /${foo}Katze/; # Streichhölzer

So weit, so gut. Mit dem oben genannten Wissen können Sie bereits Suchen durchführen mit nur
über jeden beliebigen String-Regexp, den Sie sich vorstellen können. Hier ist ein sehr einfach Emulation der
Unix-Grep-Programm:

% Katze > simple_grep
#!/ Usr / bin / perl
$regexp = Verschiebung;
während (<>) {
drucken, wenn /$regexp/;
}
^D

% chmod +x simple_grep

% simple_grep abba /usr/dict/words
Babbage
Kohl
Kohl
Sabbat
Sabbathisieren
Sabbathisiert
Sabbatical
Scheide
Scheiden

Dieses Programm ist leicht verständlich. "#!/ Usr / bin / perl" ist die Standardmethode zum Aufrufen eines
Perl-Programm aus der Shell. "$regexp = shift;" speichert das erste Kommandozeilenargument als
der zu verwendende reguläre Ausdruck, wobei die restlichen Befehlszeilenargumente wie folgt behandelt werden
Dateien. "while (<>)" durchläuft alle Zeilen in allen Dateien. Für jede Zeile,
"print if /$regexp/;" gibt die Zeile aus, wenn der reguläre Ausdruck mit der Zeile übereinstimmt. In dieser Zeile
„print“ und „/$regexp/“ verwenden implizit die Standardvariable $_.

Bei allen oben genannten regulären Ausdrücken war es so, dass, wenn der reguläre Ausdruck irgendwo in der Zeichenfolge übereinstimmte,
als Übereinstimmung betrachtet. Manchmal möchten wir jedoch angeben woher in der Zeichenfolge die
regexp sollte versuchen zuzuordnen. Dazu verwenden wir die Anker Metazeichen "^" und
"$". Der Anker "^" bedeutet Übereinstimmung am Anfang der Zeichenfolge und der Anker "$" bedeutet
match am Ende der Zeichenfolge oder vor einem Zeilenumbruch am Ende der Zeichenfolge. Hier ist, wie
Sie werden verwendet:

"Haushälterin" =~ /Haushälterin/; # Streichhölzer
"Haushälterin" =~ /^Haushälterin/; # passt nicht zusammen
"Haushälterin" =~ /keeper$/; # Streichhölzer
"Haushälterin\n" =~ /keeper$/; # Streichhölzer

Der zweite reguläre Ausdruck stimmt nicht überein, weil "^" "keeper" so einschränkt, dass es nur am
Anfang der Zeichenfolge, aber "housekeeper" hat keeper in der Mitte. Die dritte
Regexp stimmt überein, da das "$" "Keeper" nur am Ende des
String.

Wenn sowohl "^" als auch "$" gleichzeitig verwendet werden, muss der reguläre Ausdruck sowohl mit dem
Anfang und Ende der Zeichenfolge, d. h. der reguläre Ausdruck entspricht der gesamten Zeichenfolge. Betrachten Sie

"Keeper" =~ /^keep$/; # stimmt nicht überein
"Keeper" =~ /^Keeper$/; # Übereinstimmungen
"" =~ /^$/; # ^$ entspricht einer leeren Zeichenfolge

Der erste reguläre Ausdruck passt nicht, da die Zeichenfolge mehr als "keep" enthält. Da die
Der zweite reguläre Ausdruck ist genau die Zeichenfolge, die er entspricht. Die Verwendung von "^" und "$" in einem regulären Ausdruck
erzwingt die Übereinstimmung der gesamten Zeichenfolge, sodass Sie die vollständige Kontrolle darüber haben, welche Zeichenfolgen
passen und welche nicht. Angenommen, Sie suchen einen Kerl namens Bert, der in einer Zeichenfolge
von ihm selbst:

"dogbert" =~ /bert/; # passt, aber nicht zu dem, was Sie wollen

"dilbert" =~ /^bert/; # passt nicht, aber ..
"bertram" =~ /^bert/; # Übereinstimmungen, also immer noch nicht gut genug

"bertram" =~ /^bert$/; # passt nicht, gut
"dilbert" =~ /^bert$/; # passt nicht, gut
"bert" =~ /^bert$/; # Übereinstimmungen, perfekt

Natürlich könnte man im Falle einer Literalzeichenfolge genauso gut die Zeichenfolge verwenden
Vergleich "$string eq 'bert'" und es wäre effizienter. Der reguläre Ausdruck "^...$"
wird wirklich nützlich, wenn wir die leistungsstärkeren Regexp-Tools unten hinzufügen.

Die richtigen Charakter Unterricht
Obwohl man mit den oben genannten String-Regexps schon eine ganze Menge machen kann, haben wir nur
kratzte an der Oberfläche der regulären Ausdruckstechnologie. In diesem und den folgenden Abschnitten
Wir werden Regexp-Konzepte (und zugehörige Metazeichennotationen) einführen, die es ermöglichen
ein regulärer Ausdruck, der nicht nur eine einzelne Zeichenfolge darstellt, sondern eine ganze Klasse von ihnen.

Ein solches Konzept ist das einer Charakter KlasseEine Zeichenklasse ermöglicht eine Reihe von möglichen
Zeichen, anstatt nur ein einzelnes Zeichen, das an einem bestimmten Punkt in einem
regexp. Sie können Ihre eigenen benutzerdefinierten Zeichenklassen definieren. Diese sind durch Klammern gekennzeichnet
"[...]", mit der Menge der Zeichen, die möglicherweise darin übereinstimmen. Hier sind einige
Beispiele:

/Katze/; # stimmt mit 'Katze' überein
/[bcr]at/; # entspricht „Fledermaus“, „Katze“ oder „Ratte“
/item[0123456789]/; # entspricht 'item0' oder ... oder 'item9'
"abc" =~ /[Kabine]/; # stimmt mit 'a' überein

Obwohl in der letzten Anweisung „c“ das erste Zeichen in der Klasse ist, stimmt „a“ überein
weil die erste Zeichenposition in der Zeichenfolge der früheste Punkt ist, an dem das
Regexp kann übereinstimmen.

/[yY][eE][sS]/; # Übereinstimmung mit 'ja' ohne Beachtung der Groß-/Kleinschreibung
# 'ja', 'ja', 'ja' usw.

Dieser reguläre Ausdruck zeigt eine häufige Aufgabe: die Durchführung einer Groß-/Kleinschreibungsunabhängigen Übereinstimmung. Perl bietet eine Möglichkeit
die Klammern zu vermeiden, indem man einfach ein 'i' an das Ende der Übereinstimmung anhängt. Dann
"/[yY][eE][sS]/;" kann als "/yes/i;" umgeschrieben werden. Das 'i' steht für Groß- und Kleinschreibung und
ist ein Beispiel für eine Modifikator der Matching-Operation. Wir werden später noch weitere Modifikatoren kennenlernen
im Tutorial.

Wir haben im obigen Abschnitt gesehen, dass es gewöhnliche Charaktere gab, die repräsentierten
selbst und Sonderzeichen, die einen Backslash "\" zur Darstellung benötigten.
Dasselbe gilt für eine Zeichenklasse, aber die Sätze der normalen und Sonderzeichen
innerhalb einer Zeichenklasse unterscheiden sich von denen außerhalb einer Zeichenklasse. Die spezielle
Zeichen für eine Zeichenklasse sind "-]\^$" (und das Mustertrennzeichen, was auch immer es ist).
"]" ist besonders, weil es das Ende einer Zeichenklasse bezeichnet. "$" ist besonders, weil es
bezeichnet eine skalare Variable. "\" ist besonders, weil es in Escape-Sequenzen verwendet wird, genau wie
wie oben. So werden die Sonderzeichen "]$\" behandelt:

/[\]c]def/; # stimmt mit ']def' oder 'cdef' überein
$x = 'bcr';
/[$x]at/; # entspricht „Fledermaus“, „Katze“ oder „Ratte“
/[\$x]at/; # stimmt mit '$at' oder 'xat' überein
/[\\$x]at/; # stimmt mit '\at', 'bat, 'cat' oder 'rat' überein

Die letzten beiden sind etwas knifflig. In "[\$x]" schützt der Backslash das Dollarzeichen, also
Die Zeichenklasse hat zwei Mitglieder: "$" und "x". In "[\\$x]" ist der Backslash geschützt,
Daher wird $x als Variable behandelt und in Anführungszeichen gesetzt.

Das Sonderzeichen '-' fungiert als Bereichsoperator innerhalb von Zeichenklassen, so dass ein
zusammenhängende Zeichensätze können als Bereich geschrieben werden. Mit Bereichen wird die unhandliche
Aus "[0123456789]" und "[abc...xyz]" werden die schlanken "[0-9]" und "[az]". Einige Beispiele sind

/item[0-9]/; # stimmt mit 'item0' oder ... oder 'item9' überein
/[0-9bx-z]aa/; # entspricht '0aa', ..., '9aa',
# 'baa', 'xaa', 'yaa' oder 'zaa'
/[0-9a-fA-F]/; # entspricht einer hexadezimalen Ziffer
/[0-9a-zA-Z_]/; # entspricht einem "Wort"-Zeichen,
# wie die in einem Perl-Variablennamen

Wenn '-' das erste oder letzte Zeichen in einer Zeichenklasse ist, wird es wie ein gewöhnliches Zeichen behandelt
Zeichen; "[-ab]", "[ab-]" ​​und "[a\-b]" sind alle gleichwertig.

Das Sonderzeichen "^" an erster Stelle einer Zeichenklasse bezeichnet a negiert
Charakter Klasse, die jedem Zeichen außer denen in den Klammern entspricht. Beide und
"[^...]" muss mit einem Zeichen übereinstimmen, sonst schlägt die Übereinstimmung fehl. Dann

/[^a]at/; # stimmt nicht mit 'aat' oder 'at' überein, aber passt
# alle anderen 'bat', 'cat, '0at', '%at' usw.
/[^0-9]/; # entspricht einem nicht numerischen Zeichen
/[a^]at/; # stimmt mit 'aat' oder '^at' überein; hier ist '^' gewöhnlich

Jetzt kann es sogar lästig sein, "[0-9]" mehrfach zu schreiben, also im Interesse der Ersparnis
Tastenanschläge und macht reguläre Ausdrücke lesbarer. Perl verfügt über mehrere Abkürzungen für häufig verwendete
Zeichenklassen, wie unten gezeigt. Seit der Einführung von Unicode, es sei denn, die "//a"
Modifikator ist in Kraft, diese Zeichenklassen entsprechen mehr als nur ein paar Zeichen in
den ASCII-Bereich.

· \d entspricht einer Ziffer, nicht nur [0-9], sondern auch Ziffern aus nicht-lateinischen Schriften

· \s entspricht einem Leerzeichen, der Menge [\ \t\r\n\f] und anderen

· \w entspricht einem Wortzeichen (alphanumerisch oder _), nicht nur [0-9a-zA-Z_], sondern auch Ziffern
und Zeichen aus nicht-römischen Schriften

· \D ist ein negiertes \d; es stellt jedes andere Zeichen als eine Ziffer oder [^\d] dar

· \S ist ein negiertes \s; es stellt jedes beliebige Zeichen dar, das kein Leerzeichen ist [^\s].

· \W ist ein negiertes \w; es stellt jedes Nicht-Wortzeichen dar [^\w]

· Der Punkt '.' steht für jedes Zeichen außer "\n" (es sei denn, der Modifikator "//s" ist aktiv,
wie unten erläutert).

· \N, wie der Punkt, entspricht jedem Zeichen außer "\n", aber es tut dies unabhängig von
ob der Modifikator „//s“ wirksam ist.

Der Modifikator "//a", verfügbar ab Perl 5.14, wird verwendet, um die Übereinstimmungen von
\d, \s und \w auf die im ASCII-Bereich. Es ist sinnvoll, Ihr Programm davon abzuhalten,
unnötigerweise dem vollständigen Unicode (und den damit verbundenen Sicherheitsaspekten) ausgesetzt zu sein
wenn Sie nur englischähnlichen Text verarbeiten möchten. (Das "a" kann verdoppelt werden, "//aa", um
bieten noch mehr Einschränkungen, indem sie die Groß- und Kleinschreibung ignorierende Zuordnung von ASCII-
ASCII-Zeichen; andernfalls würde ein Unicode-„Kelvin-Zeichen“ unabhängig von der Groß- und Kleinschreibung mit „k“ oder „K“ übereinstimmen.)

Die Abkürzungen "\d\s\w\D\S\W" können sowohl innerhalb als auch außerhalb von Klammern verwendet werden.
Zeichenklassen. Hier sind einige verwendete:

/\d\d:\d\d:\d\d/; # entspricht einem hh:mm:ss-Zeitformat
/[\d\s]/; # entspricht einer beliebigen Ziffer oder Leerzeichen
/\w\W\w/; # stimmt mit einem Wort char überein, gefolgt von a
# Nicht-Wort-Zeichen, gefolgt von einem Wort-Zeichen
/..rt/; # stimmt mit zwei beliebigen Zeichen überein, gefolgt von 'rt'
/Ende\./; # stimmt mit 'Ende' überein.
/Ende[.]/; # dasselbe, entspricht 'end'.

Da ein Punkt ein Metazeichen ist, muss er maskiert werden, um als normales Zeichen zu gelten.
Punkt. Da beispielsweise "\d" und "\w" Zeichenfolgen sind, ist es falsch,
Stellen Sie sich "[^\d\w]" als "[\D\W]" vor; tatsächlich ist "[^\d\w]" dasselbe wie "[^\w]", was das
dasselbe wie "[\W]". Denken Sie an DeMorgans Gesetze.

Tatsächlich sind die Abkürzungen Punkt und "\d\s\w\D\S\W" selbst Arten von
Zeichenklassen, also sind die in Klammern eingeschlossenen nur eine Art von Zeichen
Klasse. Wenn wir eine Unterscheidung treffen müssen, bezeichnen wir sie als "eingeklammerte Zeichen
Klassen."

Ein in einfachen regulären Ausdrücken nützlicher Anker ist der Wort Anker "\b". Dies entspricht einer Grenze
zwischen einem Wortzeichen und einem Nicht-Wortzeichen "\w\W" oder "\W\w":

$x = "Hauskatze verkettet Haus und Katze";
$x =~ /Katze/; # entspricht Katze in „Hauskatze“
$x =~ /\bcat/; # stimmt mit Katze in 'catenates' überein
$x =~ /Katze\b/; # stimmt mit Katze in 'Hauskatze' überein
$x =~ /\bcat\b/; # stimmt mit 'Katze' am Ende des Strings überein

Beachten Sie, dass im letzten Beispiel das Ende der Zeichenfolge als Wortgrenze betrachtet wird.

Für die Verarbeitung natürlicher Sprache (damit beispielsweise Apostrophe in Wörtern enthalten sind),
verwende stattdessen "\b{wb}"

"nicht" =~ / .+? \b{wb} /x; # stimmt mit der gesamten Zeichenfolge überein

Sie fragen sich vielleicht, warum '.' auf alles außer "\n" passt - warum nicht auf jedes Zeichen? Der Grund
ist, dass man oft mit Zeilen vergleicht und die Zeilenumbrüche ignorieren möchte
Zeichen. Während beispielsweise die Zeichenfolge "\n" eine Zeile darstellt, möchten wir
Betrachten Sie es als leer. Dann

"" =~ /^$/; # Übereinstimmungen
"\n" =~ /^$/; # Übereinstimmungen, $-Anker vor "\n"

"" =~ /./; # passt nicht; es braucht ein Zeichen
"" =~ /^.$/; # passt nicht; es benötigt ein Zeichen
"\n" =~ /^.$/; # passt nicht; es wird ein anderes Zeichen als "\n" benötigt
"a" =~ /^.$/; # Übereinstimmungen
"a\n" =~ /^.$/; # Übereinstimmungen, $-Anker vor "\n"

Dieses Verhalten ist praktisch, da wir normalerweise Zeilenumbrüche ignorieren wollen, wenn wir zählen und
Zeichen in einer Zeile abgleichen. Manchmal möchten wir jedoch Zeilenumbrüche im Auge behalten. Wir
Vielleicht möchten Sie sogar "^" und "$" am Anfang und Ende der Zeilen innerhalb der Zeichenfolge verankern,
anstatt nur den Anfang und das Ende der Zeichenfolge. Perl ermöglicht es uns, zwischen
Ignorieren und Beachten von Zeilenumbrüchen durch Verwendung der Modifikatoren „//s“ und „//m“. „//s“
und "//m" stehen für Single Line und Multi Line und legen fest, ob ein String
als eine fortlaufende Zeichenfolge oder als eine Reihe von Zeilen behandelt werden. Die beiden Modifikatoren wirken sich auf zwei
Aspekte der Interpretation des regulären Ausdrucks: 1) wie die Zeichenklasse '.' definiert ist und
2) wo die Anker "^" und "$" übereinstimmen können. Hier sind die vier möglichen
Kombinationen:

· keine Modifikatoren (//): Standardverhalten. „.“ entspricht jedem Zeichen außer „\n“. „^“
passt nur am Anfang der Zeichenfolge und "$" passt nur am Ende oder davor
eine neue Zeile am Ende.

· s-Modifikator (//s): Behandeln Sie die Zeichenfolge als eine einzelne lange Zeile. '.' entspricht jedem Zeichen, auch
"\n". "^" passt nur am Anfang der Zeichenfolge und "$" passt nur am Ende
oder vor einem Zeilenumbruch am Ende.

· m-Modifikator (//m): Behandeln Sie die Zeichenfolge als eine Reihe mehrerer Zeilen. „.“ steht für jedes Zeichen
außer "\n". "^" und "$" können am Anfang oder Ende von für Linie innerhalb der
String.

· beide Modifikatoren s und m (//sm): Behandeln Sie die Zeichenfolge als eine einzelne lange Zeile, erkennen Sie jedoch mehrere
Zeilen. '.' entspricht jedem Zeichen, auch "\n". "^" und "$" hingegen können übereinstimmen
zu Beginn oder Ende für Zeile innerhalb der Zeichenfolge.

Hier sind Beispiele für „//s“ und „//m“ in Aktion:

$x = "Es war einmal ein Mädchen,\ndas in Perl programmierte\n";

$x =~ /^Who/; # stimmt nicht überein, "Who" steht nicht am Anfang der Zeichenfolge
$x =~ /^Who/s; # stimmt nicht überein, "Who" steht nicht am Anfang der Zeichenfolge
$x =~ /^Who/m; # entspricht "Who" am Anfang der zweiten Zeile
$x =~ /^Who/sm; # entspricht "Who" am Anfang der zweiten Zeile

$x =~ /girl.Who/; # stimmt nicht überein, "." stimmt nicht überein mit "\n"
$x =~ /girl.Who/s; # entspricht "." entspricht "\n"
$x =~ /girl.Who/m; # stimmt nicht überein, "." stimmt nicht überein mit "\n"
$x =~ /girl.Who/sm; # entspricht "." entspricht "\n"

Meistens ist das Standardverhalten das gewünschte, aber "//s" und "//m" sind
gelegentlich sehr nützlich. Wenn "//m" verwendet wird, kann der Anfang der Zeichenfolge immer noch
mit "\A" abgeglichen und das Ende der Zeichenfolge kann immer noch mit den Ankern "\Z" abgeglichen werden
(entspricht sowohl dem Ende als auch dem Zeilenumbruch davor, wie „$“) und „\z“ (entspricht nur dem Ende):

$x =~ /^Who/m; # entspricht "Who" am Anfang der zweiten Zeile
$x =~ /\AHo/m; # stimmt nicht überein, "Who" steht nicht am Anfang der Zeichenfolge

$x =~ /girl$/m; # Übereinstimmungen, "girl" am Ende der ersten Zeile
$x =~ /girl\Z/m; # stimmt nicht überein, „girl“ steht nicht am Ende der Zeichenfolge

$x =~ /Perl\Z/m; # Übereinstimmungen, "Perl" steht im Zeilenumbruch vor dem Ende
$x =~ /Perl\z/m; # stimmt nicht überein, "Perl" steht nicht am Ende der Zeichenfolge

Wir wissen nun, wie man in einem regulären Ausdruck Auswahlmöglichkeiten zwischen Zeichenklassen schafft. Wie wäre es mit
Auswahlmöglichkeiten zwischen Wörtern oder Zeichenfolgen? Solche Auswahlmöglichkeiten werden im nächsten Abschnitt beschrieben.

Abgleichen fehlen uns die Worte. or zur Abwicklung, Integrierung, Speicherung und
Manchmal möchten wir, dass unser regulärer Ausdruck mit verschiedenen möglichen Wörtern übereinstimmt oder
Zeichenketten. Dies wird durch die Verwendung der Wechsel Metazeichen "|". Um
Wenn "Hund" oder "Katze" gefunden wird, bilden wir den regulären Ausdruck "Hund|Katze". Wie zuvor versucht Perl, die
regexp an der frühestmöglichen Stelle im String. An jeder Zeichenposition wird Perl
versucht zunächst, die erste Alternative, "dog", zu finden. Wenn "dog" nicht passt, versucht Perl
Versuchen Sie dann die nächste Alternative, "cat". Wenn "cat" auch nicht übereinstimmt, schlägt die Übereinstimmung fehl
und Perl springt zur nächsten Position im String. Einige Beispiele:

"Katzen und Hunde" =~ /Katze|Hund|Vogel/; # stimmt mit "Katze" überein
"Katzen und Hunde" =~ /Hund|Katze|Vogel/; # stimmt mit "Katze" überein

Obwohl "Hund" die erste Alternative im zweiten regulären Ausdruck ist, kann "Katze" übereinstimmen
früher in der Saite.

"Katzen" =~ /c|ca|Katze|Katzen/; # stimmt mit "c" überein
"Katzen" =~ /Katzen|Katze|ca|c/; # stimmt mit "Katzen" überein

Hier stimmen alle Alternativen an der ersten Zeichenfolgeposition überein, daher ist die erste Alternative
diejenige, die passt. Wenn einige der Alternativen Kürzungen der anderen sind, setzen Sie die
Wählen Sie zuerst die längsten aus, um ihnen eine Übereinstimmung zu ermöglichen.

"cab" =~ /a|b|c/ # entspricht "c"
# /a|b|c/ == /[abc]/

Das letzte Beispiel zeigt, dass Zeichenklassen wie Zeichenwechsel sind.
An einer gegebenen Zeichenposition die erste Alternative, die die Regexp-Übereinstimmung zulässt
Erfolgreich ist derjenige, der übereinstimmt.

Gruppierung und hierarchische Abstimmung
Die Alternation ermöglicht einem regulären Ausdruck die Auswahl zwischen Alternativen, aber für sich genommen ist sie
unbefriedigend. Der Grund ist, dass jede Alternative ein ganzer regulärer Ausdruck ist, aber manchmal wollen wir
Alternativen für nur einen Teil eines regulären Ausdrucks. Nehmen wir zum Beispiel an, wir wollen suchen nach
Hauskatzen oder Haushälterinnen. Der reguläre Ausdruck "Hauskatze|Haushälterin" trifft dies zu, ist aber
ineffizient, weil wir "Haus" zweimal eingeben mussten. Es wäre schön, Teile der
Reguläre Ausdrücke müssen konstant sein, wie „Haus“, und einige Teile haben Alternativen, wie „Katze|Wächter“.

Die Gruppierung Metazeichen "()" lösen dieses Problem. Durch die Gruppierung können Teile eines regulären Ausdrucks
als eine Einheit behandelt werden. Teile eines regulären Ausdrucks werden gruppiert, indem sie in
Klammern. So könnten wir das Problem "housecat|housekeeper" lösen, indem wir den regulären Ausdruck wie folgt formulieren:
"Haus(Katze|Wächter)". Der reguläre Ausdruck "Haus(Katze|Wächter)" bedeutet "Haus" gefolgt von
entweder "Katze" oder "Keeper". Einige weitere Beispiele sind

/(a|b)b/; # stimmt mit 'ab' oder 'bb' überein
/(ac|b)b/; # entspricht „acb“ oder „bb“
/(^a|b)c/; # stimmt mit 'ac' am Anfang der Zeichenfolge oder 'bc' überall überein
/(a|[bc])d/; # entspricht „ad“, „bd“ oder „cd“

/Haus(Katze|)/; # entspricht entweder 'housecat' oder 'house'
/haus(Katze(n|)|)/; # entspricht entweder 'housecats' oder 'housecat' oder
# 'Haus'. Hinweisgruppen können verschachtelt werden.

/(19|20|)\d\d/; # entspricht den Jahren 19xx, 20xx oder dem Y2K-Problem, xx
"20" =~ /(19|20|)\d\d/; # stimmt mit der Nullalternative '()\d\d' überein,
# weil '20\d\d' nicht übereinstimmen kann

Alternationen verhalten sich in Gruppen genauso wie außerhalb von ihnen: An einer gegebenen Saitenposition
Die am weitesten links stehende Alternative, die eine Übereinstimmung des regulären Ausdrucks ermöglicht, wird gewählt. Im letzten Beispiel bei
Die erste Zeichenfolgeposition, "20", entspricht der zweiten Alternative, aber es bleibt nichts übrig
um die nächsten beiden Ziffern "\d\d" abzugleichen. Perl geht also zur nächsten Alternative über, die
ist die Nullalternative und das funktioniert, da „20“ zweistellig ist.

Der Prozess, eine Alternative auszuprobieren, zu prüfen, ob sie passt, und dann zur nächsten überzugehen
Alternative, während man in der Zeichenfolge zurückgeht, von wo aus die vorherige Alternative versucht wurde,
wenn nicht, heißt es RückzieherDer Begriff „Backtracking“ kommt von der Idee, dass
Das Abgleichen eines regulären Ausdrucks ist wie ein Spaziergang im Wald. Das erfolgreiche Abgleichen eines regulären Ausdrucks ist wie
Ankunft am Ziel. Es gibt viele mögliche Ausgangspunkte, einen für jede Zeichenfolge
Position, und jeder wird der Reihe nach von links nach rechts ausprobiert. Von jedem Ausgangspunkt aus kann es
viele Wege, von denen einige Sie ans Ziel bringen, und einige sind Sackgassen. Wenn Sie gehen
entlang eines Pfades und in eine Sackgasse geraten, müssen Sie den Pfad zurück zu einem früheren
Punkt, um einen anderen Weg zu versuchen. Wenn Sie Ihr Ziel erreichen, stoppen Sie sofort und vergessen
über das Ausprobieren aller anderen Wege. Sie sind hartnäckig, und nur wenn Sie alle ausprobiert haben
Wanderwege von allen Ausgangspunkten und nicht am Ziel angekommen, erklären Sie
Fehler. Um konkret zu werden, hier ist eine Schritt-für-Schritt-Analyse dessen, was Perl tut, wenn es versucht
um dem regulären Ausdruck zu entsprechen

"abcde" =~ /(abd|abc)(df|d|de)/;

0 Beginnen Sie mit dem ersten Buchstaben der Zeichenfolge „a“.

1 Versuchen Sie die erste Alternative in der ersten Gruppe „abd“.

2 Übereinstimmung mit „a“ gefolgt von „b“. So weit, so gut.

3 'd' im regulären Ausdruck passt nicht zu 'c' im String – eine Sackgasse. Gehen Sie also zwei
Zeichen und wählen Sie die zweite Alternative in der ersten Gruppe „abc“.

4 Match 'a' gefolgt von 'b' gefolgt von 'c'. Wir sind auf dem richtigen Weg und haben die
erste Gruppe. Setzen Sie $1 auf „abc“.

5 Gehen Sie zur zweiten Gruppe und wählen Sie die erste Alternative „df“.

6 Ordnen Sie das „d“ zu.

7 Das 'f' im regulären Ausdruck passt nicht zum 'e' im String, also eine Sackgasse. Zurückverfolgen
Zeichen und wählen Sie die zweite Alternative in der zweiten Gruppe „d“.

8 Treffer mit „d“. Die zweite Gruppierung ist erfüllt, also setzen Sie $2 auf „d“.

9 Wir sind am Ende des regulären Ausdrucks, also sind wir fertig! Wir haben 'abcd' aus dem
Zeichenfolge „abcde“.

Zu dieser Analyse sind einige Dinge zu beachten. Erstens: Die dritte Alternative in
Die zweite Gruppe 'de' erlaubt auch eine Übereinstimmung, aber wir haben angehalten, bevor wir dazu kamen - an einem bestimmten
Charakterposition, ganz links gewinnt. Zweitens konnten wir ein Match am ersten
Zeichenposition der Zeichenfolge 'a'. Wenn es an der ersten Position keine Übereinstimmungen gab,
Perl würde zur zweiten Zeichenposition „b“ wechseln und den Abgleich erneut versuchen.
Erst wenn alle möglichen Pfade an allen möglichen Zeichenpositionen ausgeschöpft sind,
Perl gibt auf und erklärt „$string =~ /(abd|abc)(df|d|de)/;“ für falsch.

Trotz all dieser Arbeit erfolgt die Regexp-Übereinstimmung bemerkenswert schnell. Um dies zu beschleunigen,
Perl kompiliert den regulären Ausdruck in eine kompakte Folge von Opcodes, die oft in eine
Prozessor-Cache. Wenn der Code ausgeführt wird, können diese Opcodes dann mit voller Leistung laufen
und sehr schnell suchen.

Extrahieren Streichhölzer
Die Gruppierungsmetazeichen "()" erfüllen noch eine ganz andere Funktion: Sie
ermöglichen die Extraktion der Teile einer Zeichenfolge, die übereinstimmten. Dies ist sehr nützlich, um zu finden
heraus, was übereinstimmte und für die Textverarbeitung im Allgemeinen. Für jede Gruppierung wird der Teil, der
Die darin enthaltenen Matched-Objekte werden in die speziellen Variablen $1, $2 usw. eingefügt. Sie können genauso verwendet werden wie
gewöhnliche Variablen:

# Stunden, Minuten, Sekunden extrahieren
if ($time =~ /(\d\d):(\d\d):(\d\d)/) { # entspricht dem Format hh:mm:ss
$Stunden = $1;
$Minuten = $ 2;
$Sekunden = $3;
}

Nun wissen wir, dass im Skalarkontext "$time =~ /(\d\d):(\d\d):(\d\d)/" einen wahren Wert zurückgibt oder
falscher Wert. Im Listenkontext gibt es jedoch die Liste der übereinstimmenden Werte zurück
"($1,$2,$3)". Wir könnten den Code also kompakter schreiben als

# Stunden, Minuten, Sekunden extrahieren
($Stunden, $Minuten, $Sekunden) = ($Zeit =~ /(\d\d):(\d\d):(\d\d)/);

Wenn die Gruppierungen in einem regulären Ausdruck verschachtelt sind, erhält $1 die Gruppe mit der am weitesten links liegenden Öffnung
Klammer, $2 die nächste öffnende Klammer usw. Hier ist ein regulärer Ausdruck mit verschachtelten Gruppen:

/(ab(cd|ef)((gi)|j))/;
1 2 34

Wenn dieser reguläre Ausdruck übereinstimmt, enthält $1 eine Zeichenfolge, die mit „ab“ beginnt, und $2 ist entweder auf „cd“ gesetzt.
oder 'ef', $3 ist entweder gleich 'gi' oder 'j', und $4 ist entweder gleich 'gi', genau wie $3, oder es
bleibt undefiniert.

Der Einfachheit halber setzt Perl $+ auf die Zeichenfolge mit der höchsten Nummer $1, $2,..., die
wurde zugewiesen (und, etwas damit verbunden, $^N zum Wert von $1, $2,... zuletzt
zugewiesen; d. h. die $1, $2,..., die mit der rechten schließenden Klammer verknüpft sind, die in
das Spiel).

Rückverweise
Eng verbunden mit den Matching-Variablen $1, $2, ... sind die Rückreferenzen "\g1",
"\g2",... Rückverweise sind einfach passende Variablen, die verwendet werden können innerhalb ein regulärer Ausdruck.
Das ist eine wirklich nette Funktion; was später in einem regulären Ausdruck übereinstimmt, wird davon abhängig gemacht, was
zuvor im regulären Ausdruck gefunden. Angenommen, wir wollten nach doppelten Wörtern in einem Text suchen,
wie „der, der, die“. Der folgende reguläre Ausdruck findet alle dreistelligen Doppelzeichen mit einem Leerzeichen dazwischen:

/\b(\w\w\w)\s\g1\b/;

Die Gruppierung weist \g1 einen Wert zu, so dass für beide die gleiche 3-Buchstaben-Sequenz verwendet wird.
Teile.

Eine ähnliche Aufgabe besteht darin, Wörter zu finden, die aus zwei identischen Teilen bestehen:

% simple_grep '^(\w\w\w\w|\w\w\w|\w\w|\w)\g1$' /usr/dict/words
Beriberi
Booboo
Kokos
Mama
Ich murmle
Papa

Der reguläre Ausdruck hat eine einzelne Gruppierung, die 4-Buchstaben-Kombinationen berücksichtigt, dann 3-Buchstaben
Kombinationen usw. und verwendet "\g1", um nach einer Wiederholung zu suchen. Obwohl $1 und "\g1"
Das Gleiche gilt, es sollte darauf geachtet werden, nur die übereinstimmenden Variablen $1, $2,... zu verwenden aussen a
Regexp und Rückverweise "\g1", "\g2",... nur innerhalb ein regulärer Ausdruck; wenn Sie dies nicht tun, kann dies zu
überraschende und unbefriedigende Ergebnisse.

Relativ Rückreferenzen
Das Zählen der öffnenden Klammern, um die richtige Zahl für einen Rückverweis zu erhalten, ist fehlerhaft.
anfällig, sobald mehr als eine Erfassungsgruppe vorhanden ist. Eine bequemere Technik
wurde mit Perl 5.10 verfügbar: relative Rückverweise. Um auf die unmittelbar
Die vorhergehende Capture-Gruppe kann nun mit "\g{-1}" angegeben werden, die vorletzte ist über
"\g{-2}" und so weiter.

Ein weiterer guter Grund neben der Lesbarkeit und Wartbarkeit für die Verwendung von relativen
Rückverweise werden durch das folgende Beispiel veranschaulicht, wo ein einfaches Muster für
Es werden passende besondere Zeichenfolgen verwendet:

$a99a = '([az])(\d)\g2\g1'; # entspricht a11a, g22g, x33x usw.

Da wir dieses Muster nun als praktische Zeichenfolge gespeichert haben, könnten wir versucht sein, es als
ein Teil eines anderen Musters:

$Zeile = "Code=e99e";
if ($line =~ /^(\w+)=$a99a$/){ # unerwartetes Verhalten!
drucken "$1 ist gültig\n";
} Else {
print "fehlerhafte Zeile: '$line'\n";
}

Aber das passt nicht, zumindest nicht so, wie man es erwarten würde. Erst nach dem Einfügen des
interpoliert $a99a und betrachtet den resultierenden Volltext des regulären Ausdrucks, ist es offensichtlich, dass
Die Rückverweise sind nach hinten losgegangen. Der Teilausdruck "(\w+)" hat die Nummer 1 geschnappt und
die Gruppen in $a99a um einen Rang herabgestuft. Dies kann durch die Verwendung relativer
Rückverweise:

$a99a = '([az])(\d)\g{-1}\g{-2}'; # sicher für die Interpolation

Namens Rückreferenzen
Perl 5.10 führte auch benannte Capture-Gruppen und benannte Rückverweise ein. Um einen Namen anzuhängen
zu einer Erfassungsgruppe schreiben Sie entweder "(? ...)" oder "(?'name'...)". Die
Rückverweise können dann als "\g{name}" geschrieben werden. Es ist zulässig, die gleichen
Namen zu mehr als einer Gruppe hinzufügen, aber dann kann nur der am weitesten links stehende der gleichnamigen Gruppe
referenziert. Außerhalb des Musters ist eine benannte Erfassungsgruppe über das "%+" zugänglich
hash

Angenommen, wir müssen Kalenderdaten abgleichen, die in einer der drei
Formate jjjj-mm-tt, mm/tt/jjjj oder tt.mm.jjjj, können wir drei geeignete Muster schreiben, wobei
Wir verwenden 'd', 'm' und 'y' als Namen der Gruppen, die die zugehörigen
Komponenten eines Datums. Die Matching-Operation kombiniert die drei Muster als Alternativen:

$fmt1 = '(? \d\d\d\d)-(? \d\d)-(? \d\d)';
$fmt2 = '(? \d\d)/(? \d\d)/(? \d\d\d\d)';
$fmt3 = '(? \d\d)\.(? \d\d)\.(? \d\d\d\d)';
für mein $d qw( 2006-10-21 15.01.2007 10/31/2005 ){
wenn ( $d =~ m{$fmt1|$fmt2|$fmt3} ){
drucken "Tag=$+{d} Monat=$+{m} Jahr=$+{y}\n";
}
}

Wenn eine der Alternativen übereinstimmt, muss der Hash "%+" die drei Schlüsselwerte enthalten
Paaren.

Alternative Erfassung Gruppe Nummerierung
Eine weitere Technik zur Nummerierung von Erfassungsgruppen (ebenfalls ab Perl 5.10) befasst sich mit der
Problem der Bezugnahme auf Gruppen innerhalb einer Reihe von Alternativen. Betrachten Sie ein Muster für
passend zur Tageszeit, ziviler oder militärischer Stil:

wenn ( $Zeit =~ /(\d\d|\d):(\d\d)|(\d\d)(\d\d)/ ){
# Stunde und Minute verarbeiten
}

Die Verarbeitung der Ergebnisse erfordert eine zusätzliche if-Anweisung, um zu bestimmen, ob $1 und $2
oder $3 und $4 enthalten die Leckereien. Es wäre einfacher, wenn wir die Gruppennummern 1 und 2 verwenden könnten
auch in der zweiten Alternative, und genau das ist die eingeklammerte Konstruktion
"(?|...)", um eine Alternative zu erreichen. Hier ist eine erweiterte Version der vorherigen
Muster:

if($time =~ /(?|(\d\d|\d):(\d\d)|(\d\d)(\d\d))\s+([AZ][AZ][AZ])/){
drucke "Stunde=$1 Minute=$2 Zone=$3\n";
}

Innerhalb der alternativen Nummerierungsgruppe beginnen die Gruppennummern für jeden
Alternative. Nach der Gruppe wird die Nummerierung mit einer Nummer höher als das erreichte Maximum fortgesetzt
über alle Alternativen hinweg.

Position Information
Zusätzlich zu den Übereinstimmungen liefert Perl auch die Positionen der Übereinstimmungen als
Inhalt der Arrays "@-" und "@+". "$-[0]" ist die Position des Anfangs des gesamten
Übereinstimmung und $+[0] ist die Position des Endes. Ähnlich ist "$-[n]" die Position des
Beginn des $n-Matches und $+[n] ist die Position des Endes. Wenn $n undefiniert ist, sind es auch
"$-[n]" und $+[n]. Dann dieser Code

$x = "Mmm ... Donut, dachte Homer";
$x =~ /^(Mmm|Igitt)\.\.\.(Donut|Erbsen)/; # Übereinstimmungen
für jeden $exp (1..$#-) {
drucken "Match $exp: '${$exp}' an Position ($-[$exp],$+[$exp])\n";
}

Drucke

Übereinstimmung 1: „Mmm“ an Position (0,3)
Übereinstimmung 2: „Donut“ an Position (6,11)

Auch wenn es in einem regulären Ausdruck keine Gruppierungen gibt, ist es dennoch möglich herauszufinden, was genau
in einem String übereinstimmen. Wenn Sie sie verwenden, setzt Perl "$`" auf den Teil des Strings vor
die Übereinstimmung, setzt $& auf den Teil der Zeichenfolge, der übereinstimmt, und setzt "$'" auf den
Teil der Zeichenfolge nach der Übereinstimmung. Ein Beispiel:

$x = "die Katze hat die Maus gefangen";
$x =~ /Katze/; # $` = 'die', $& = 'Katze', $' = 'die Maus gefangen'
$x =~ /der/; # $` = '', $& = 'der', $' = 'Katze hat die Maus gefangen'

Im zweiten Match ist "$`" gleich '', weil der reguläre Ausdruck beim ersten Zeichen übereinstimmte
Position in der Zeichenfolge und stoppte; es hat das zweite „the“ nie gesehen.

Wenn Ihr Code auf Perl-Versionen vor 5.20 ausgeführt werden soll, ist zu beachten, dass
Die Verwendung von "$`" und "$'" verlangsamt den regulären Ausdrucksabgleich erheblich, während $& ihn auf ein
in geringerem Maße, denn wenn sie in einem regulären Ausdruck in einem Programm verwendet werden, werden sie für
alle Regexps im Programm. Wenn also reine Leistung ein Ziel Ihrer Anwendung ist,
sollte vermieden werden. Wenn Sie die entsprechenden Teilzeichenfolgen extrahieren müssen, verwenden Sie "@-" und "@+"
stattdessen:

$` ist dasselbe wie substr( $x, 0, $-[0] )
$& ist dasselbe wie substr( $x, $-[0], $+[0]-$-[0] )
$' ist dasselbe wie substr( $x, $+[0] )

Ab Perl 5.10 können die Variablen "${^PREMATCH}", "${^MATCH}" und "${^POSTMATCH}"
verwendet. Diese werden nur gesetzt, wenn der Modifikator "/p" vorhanden ist. Folglich werden sie nicht
den Rest des Programms bestrafen. In Perl 5.20 sind "${^PREMATCH}", "${^MATCH}" und
"${^POSTMATCH}" sind verfügbar, unabhängig davon, ob "/p" verwendet wurde oder nicht (der Modifikator ist
ignoriert), und "$`", "$'" und $& verursachen keinen Geschwindigkeitsunterschied.

Nicht erfassend Gruppierungen
Eine Gruppe, die eine Reihe von Alternativen bündeln muss, kann nützlich sein oder auch nicht als
Erfassungsgruppe. Wenn dies nicht der Fall ist, wird lediglich eine überflüssige Ergänzung zur Menge der
verfügbare Erfassungsgruppenwerte, sowohl innerhalb als auch außerhalb des regulären Ausdrucks. Nicht erfassende
Gruppierungen, gekennzeichnet durch "(?:regexp)", ermöglichen es weiterhin, den regulären Ausdruck als einzelne Einheit zu behandeln,
aber nicht gleichzeitig eine Erfassungsgruppe einrichten. Sowohl erfassende als auch nicht erfassende
Gruppierungen dürfen im selben regulären Ausdruck koexistieren. Da keine Extraktion stattfindet,
Nicht-Erfassungsgruppierungen sind schneller als Erfassungsgruppierungen. Nicht-Erfassungsgruppierungen sind
auch praktisch, um genau auszuwählen, welche Teile eines regulären Ausdrucks extrahiert werden sollen, um zu entsprechen
Variablen:

# passt zu einer Zahl, $1-$4 sind festgelegt, aber wir wollen nur $1
/([+-]?\ *(\d+(\.\d*)?|\.\d+)([eE][+-]?\d+)?)/;

# eine Zahl schneller abgleichen, nur $1 ist festgelegt
/([+-]?\ *(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][+-]?\d+)?)/;

# eine Zahl abgleichen, erhalten Sie $1 = ganze Zahl, $2 = Exponent
/([+-]?\ *(?:\d+(?:\.\d*)?|\.\d+)(?:[eE]([+-]?\d+))?)/;

Nicht erfassende Gruppierungen sind auch nützlich, um Störelemente zu entfernen, die aus einem
Split-Operation, bei der aus irgendeinem Grund Klammern erforderlich sind:

$x = '12aba34ba5';
@num = split /(a|b)+/, $x; # @num = ('12','a','34','a','5')
@num = split /(?:a|b)+/, $x; # @num = ('12','34','5')

In Perl 5.22 und höher können alle Gruppen innerhalb eines regulären Ausdrucks auf Nicht-Erfassung eingestellt werden, indem
das neue Flag "/n":

"hallo" =~ /(hi|hallo)/n; # $1 ist nicht festgelegt!

Siehe "n" in Perlre für weitere Informationen.

Abgleichen Proben
Die Beispiele im vorherigen Abschnitt zeigen eine ärgerliche Schwäche. Wir haben nur
3-Buchstaben-Wörter oder Wortgruppen mit 4 Buchstaben oder weniger. Wir möchten in der Lage sein,
Wörter oder allgemeiner Zeichenfolgen beliebiger Länge, ohne mühsame Alternativen ausschreiben zu müssen
wie "\w\w\w\w|\w\w\w|\w\w|\w".

Genau das ist das Problem der Quantor Metazeichen „?“, „*“, „+“ und „{}“ waren
erstellt für. Sie ermöglichen es uns, die Anzahl der Wiederholungen für einen Teil eines regulären Ausdrucks zu begrenzen, den wir
als Übereinstimmung betrachten. Quantifizierer werden unmittelbar nach dem Zeichen, Zeichen
Klasse oder Gruppierung, die wir angeben möchten. Sie haben folgende Bedeutung:

· „a?“ bedeutet: 1 oder 0 Mal mit „a“ übereinstimmen

· "a*" bedeutet: 'a' 0 oder mehr Mal, also beliebig oft

· "a+" bedeutet: 'a' muss mindestens einmal vorkommen, also mindestens einmal

· „a{n,m}“ bedeutet: mindestens „n“-mal, aber nicht mehr als „m“-mal übereinstimmen.

· "a{n,}" bedeutet: mindestens "n" Mal oder öfter übereinstimmen

· "a{n}" bedeutet: Übereinstimmung genau "n"-mal

Hier sind einige Beispiele:

/[az]+\s+\d*/; # entspricht einem kleingeschriebenen Wort, mindestens einem Leerzeichen und
# beliebig viele Ziffern
/(\w+)\s+\g1/; # Übereinstimmung mit doppelten Wörtern beliebiger Länge
/y(es)?/i; # entspricht „y“, „Y“ oder einem Groß-/Kleinschreibung-unabhängigen „yes“
$Jahr =~ /^\d{2,4}$/; # Stellen Sie sicher, dass das Jahr mindestens 2 ist, aber nicht mehr
# als 4 Ziffern
$year =~ /^\d{4}$|^\d{2}$/; # bessere Übereinstimmung; dreistellige Datumsangaben weglassen
$year =~ /^\d{2}(\d{2})?$/; # das Gleiche, anders geschrieben.
# Dies erfasst jedoch die letzten beiden
# Ziffern in $1 und die andere nicht.

% simple_grep '^(\w+)\g1$' /usr/dict/words # ist das nicht einfacher?
Beriberi
Booboo
Kokos
Mama
Ich murmle
Papa

Für alle diese Quantifizierer versucht Perl, so viel von der Zeichenfolge wie möglich abzugleichen.
wobei der reguläre Ausdruck weiterhin erfolgreich sein kann. Daher versucht Perl bei "/a?.../" zunächst,
den regulären Ausdruck mit dem vorhandenen "a" abgleichen; wenn dies fehlschlägt, versucht Perl, den regulären Ausdruck abzugleichen
ohne das "a". Für den Quantifizierer "*" erhalten wir Folgendes:

$x = "die Katze im Hut";
$x =~ /^(.*)(cat)(.*)$/; # Übereinstimmungen,
# $1 = 'der'
# $2 = 'Katze'
# $3 = ' im Hut'

Das ist, was wir erwarten könnten, die Übereinstimmung findet die einzige "Katze" in der Zeichenfolge und rastet ein auf
es. Betrachten Sie jedoch diesen regulären Ausdruck:

$x =~ /^(.*)(at)(.*)$/; # Streichhölzer,
# $1 = 'die Katze im h'
# $2 = 'at'
# $3 = '' (0 Zeichen stimmen überein)

Man könnte zunächst annehmen, dass Perl das "at" in "cat" finden und dort aufhören würde, aber das
würde dem ersten Quantifizierer ".*" nicht die längstmögliche Zeichenfolge geben. Stattdessen
Der erste Quantifizierer ".*" erfasst so viel von der Zeichenfolge wie möglich und behält dabei immer noch die
Regexp-Übereinstimmung. In diesem Beispiel bedeutet das, dass die Sequenz "at" mit dem abschließenden "at" in
die Saite. Das andere wichtige Prinzip, das hier veranschaulicht wird, ist, dass, wenn es zwei oder
mehr Elemente in einem regulären Ausdruck, ganz links Quantifizierer, falls vorhanden, erhält so viel
der Zeichenfolge wie möglich, so dass der Rest des regulären Ausdrucks um die Reste kämpfen muss. Daher in
In unserem Beispiel erfasst der erste Quantifizierer ".*" den größten Teil der Zeichenfolge, während der zweite
Quantifizierer ".*" erhält den leeren String. Quantifizierer, die so viel von dem String erfassen wie
möglich sind genannt maximal Spiel or gierig Quantifizierer.

Wenn ein regulärer Ausdruck auf mehrere Arten mit einer Zeichenfolge übereinstimmen kann, können wir die Prinzipien verwenden
oben, um vorherzusagen, in welche Richtung der reguläre Ausdruck passt:

· Prinzip 0: Insgesamt wird jeder reguläre Ausdruck so früh wie möglich abgeglichen
Position in der Zeichenfolge.

· Prinzip 1: Bei einer Abwechslung "a|b|c..." ist die am weitesten links stehende Alternative, die eine
Es wird die Übereinstimmung für den gesamten regulären Ausdruck verwendet.

· Prinzip 2: Die maximal passenden Quantifizierer "?", "*", "+" und "{n,m}" werden in
allgemeine Übereinstimmung mit möglichst vielen Zeichenfolgen, wobei der gesamte reguläre Ausdruck weiterhin zulässig ist
passen.

· Prinzip 3: Wenn ein regulärer Ausdruck zwei oder mehr Elemente enthält, wird das am weitesten links liegende gierige
Quantifizierer, falls vorhanden, werden so viele Übereinstimmungen wie möglich mit der Zeichenfolge erzielt, während gleichzeitig
der gesamte reguläre Ausdruck, der übereinstimmen soll. Der nächste gierige Quantifizierer ganz links, falls vorhanden, wird versuchen,
möglichst viel von der verbliebenen Zeichenfolge abgleichen, während immer noch
so dass der gesamte reguläre Ausdruck übereinstimmt. Und so weiter, bis alle regulären Ausdruckselemente
zufrieden.

Wie wir oben gesehen haben, überschreibt Prinzip 0 die anderen. Der reguläre Ausdruck wird wie folgt abgeglichen:
so früh wie möglich, wobei die anderen Prinzipien bestimmen, wie der reguläre Ausdruck zu diesem Zeitpunkt übereinstimmt
früheste Zeichenposition.

Hier ist ein Beispiel für die Anwendung dieser Prinzipien:

$x = "Die Programmierrepublik Perl";
$x =~ /^(.+)(e|r)(.*)$/; # Übereinstimmungen,
# $1 = 'Die Programmierrepublik Pe'
# $2 = 'r'
# $3 = 'l'

Dieser reguläre Ausdruck passt zur frühesten String-Position, 'T'. Man könnte meinen, dass "e",
ganz links in der Abwechslung, würde übereinstimmen, aber "r" erzeugt die längste Zeichenfolge in der
erster Quantifizierer.

$x =~ /(m{1,2})(.*)$/; # Übereinstimmungen,
# $1 = 'mm'
# $2 = 'ing Republik Perl'

Hier ist die frühestmögliche Übereinstimmung das erste 'm' in "Programmierung". "m{1,2}" ist die
erster Quantifizierer, damit er mit einem maximalen „mm“ übereinstimmt.

$x =~ /.*(m{1,2})(.*)$/; # Übereinstimmungen,
# $1 = 'm'
# $2 = 'ing Republik Perl'

Hier wird der reguläre Ausdruck am Anfang der Zeichenfolge gefunden. Der erste Quantifizierer ".*" wird als
so viel wie möglich, sodass nur ein einzelnes „m“ für den zweiten Quantifizierer „m{1,2}“ übrig bleibt.

$x =~ /(.?)(m{1,2})(.*)$/; # Übereinstimmungen,
# $1 = 'a'
# $2 = 'mm'
# $3 = 'ing Republik Perl'

Dabei frisst „.?“ sein maximal ein Zeichen an der frühestmöglichen Position im String,
'a' in "Programmierung", wodurch "m{1,2}" die Möglichkeit hat, beide "m"'s zuzuordnen. Schließlich

"aXXXb" =~ /(X*)/; # entspricht $1 = ''

weil es keine Kopien von 'X' am Anfang der Zeichenfolge finden kann. Wenn Sie definitiv
Wenn Sie mindestens ein „X“ abgleichen möchten, verwenden Sie „X+“, nicht „X*“.

Manchmal ist Gier nicht gut. Manchmal möchten wir, dass Quantifizierer mit einem minimal Stück
von Saiten, anstatt ein maximales Stück. Zu diesem Zweck schuf Larry Wall die minimal
Spiel or nicht gierig Quantifizierer "??", "*?", "+?" und "{}?". Dies sind die üblichen
Quantifizierer mit einem angehängten "?". Sie haben folgende Bedeutung:

· „a??“ bedeutet: Finde ‚a‘ 0 oder 1 Mal. Versuche zuerst 0, dann 1.

· "a*?" bedeutet: 'a' 0 oder mehr Mal, also beliebig oft, aber so selten wie
möglich

· "a+?" bedeutet: 'a' 1 oder mehr Mal, also mindestens einmal, aber so selten wie
möglich

· "a{n,m}?" bedeutet: mindestens "n"-mal, höchstens "m"-mal, so selten wie
möglich

· „a{n,}?“ bedeutet: mindestens „n“-mal übereinstimmen, aber so wenig wie möglich

· "a{n}?" bedeutet: Übereinstimmung genau "n"-mal. Weil wir genau "n"-mal übereinstimmen, bedeutet "a{n}?"
ist gleichbedeutend mit „a{n}“ und dient lediglich der Konsistenz der Notation.

Schauen wir uns das obige Beispiel an, allerdings mit Minimalquantifikatoren:

$x = "Die Programmierrepublik Perl";
$x =~ /^(.+?)(e|r)(.*)$/; # Übereinstimmungen,
# $1 = 'Th'
# $2 = 'e'
# $3 = ' Programmierrepublik Perl '

Die minimale Zeichenfolge, die sowohl den Beginn der Zeichenfolge "^" als auch die Abwechslung zu
Die Übereinstimmung ist "Th", wobei die Alternation "e|r" mit "e" übereinstimmt. Der zweite Quantifizierer ".*" ist
frei, den Rest der Schnur zu verschlingen.

$x =~ /(m{1,2}?)(.*?)$/; # Übereinstimmungen,
# $1 = 'm'
# $2 = 'Ming-Republik Perl'

Die erste Zeichenfolgenposition, die mit diesem regulären Ausdruck übereinstimmen kann, ist das erste „m“ in „Programmierung“.
An dieser Stelle entspricht das minimale "m{1,2}?" nur einem 'm'. Obwohl das zweite
Quantifizierer ".*?" würde es vorziehen, keine Zeichen zu vergleichen, es wird durch das Ende-von-
Zeichenfolgenanker „$“, um eine Übereinstimmung mit dem Rest der Zeichenfolge zu erzielen.

$x =~ /(.*?)(m{1,2}?)(.*)$/; # Übereinstimmungen,
# $1 = 'Das Programm'
# $2 = 'm'
# $3 = 'Ming-Republik Perl'

In diesem regulären Ausdruck könnte man erwarten, dass der erste minimale Quantifizierer ".*?" mit dem leeren
Zeichenfolge, da sie nicht durch einen „^“-Anker auf die Übereinstimmung mit dem Wortanfang beschränkt ist.
Prinzip 0 gilt hier jedoch. Da es möglich ist, dass der gesamte reguläre Ausdruck
am Anfang der Zeichenfolge, es werden wir Übereinstimmung am Anfang der Zeichenfolge. Somit ist die erste
Quantifikator muss alles bis zum ersten "m" abgleichen. Der zweite Minimalquantifikator
stimmt nur mit einem „m“ überein und der dritte Quantifizierer stimmt mit dem Rest der Zeichenfolge überein.

$x =~ /(.??)(m{1,2})(.*)$/; # Übereinstimmungen,
# $1 = 'a'
# $2 = 'mm'
# $3 = 'ing Republik Perl'

Genau wie im vorherigen regulären Ausdruck kann der erste Quantifizierer „.??“ am frühesten an Position übereinstimmen
'a', also ist es so. Der zweite Quantifizierer ist gierig, also entspricht er "mm", und der dritte
stimmt mit dem Rest der Zeichenfolge überein.

Wir können das obige Prinzip 3 modifizieren, um nicht-gierige Quantifizierer zu berücksichtigen:

· Prinzip 3: Wenn ein regulärer Ausdruck zwei oder mehr Elemente enthält, wird das am weitesten links liegende gierige (nicht
gieriger) Quantifizierer, falls vorhanden, wird so viel (wenig) von der Zeichenfolge wie möglich abgleichen
wobei der gesamte reguläre Ausdruck weiterhin übereinstimmt. Der nächste ganz links gierige (nicht gierige)
Quantifizierer, falls vorhanden, versuchen, so viel (wenig) der verbleibenden Zeichenfolge abzugleichen
so viele wie möglich zur Verfügung stehen, während der gesamte reguläre Ausdruck noch passt. Und so
weiter, bis alle Regexp-Elemente erfüllt sind.

Genau wie Alternationen sind auch Quantifikatoren anfällig für Backtracking. Hier ist eine Schritt-für-Schritt-Anleitung.
Schrittweise Analyse des Beispiels

$x = "die Katze im Hut";
$x =~ /^(.*)(at)(.*)$/; # Streichhölzer,
# $1 = 'die Katze im h'
# $2 = 'at'
# $3 = '' (0 Treffer)

0 Beginnen Sie mit dem ersten Buchstaben der Zeichenfolge „t“.

1 Der erste Quantifizierer '.*' beginnt mit der Übereinstimmung mit der gesamten Zeichenfolge 'die Katze im
Hut'.

2 'a' im Regexp-Element 'at' entspricht nicht dem Ende der Zeichenfolge. Gehen Sie einen Schritt zurück
Charakter.

3 'a' im Regexp-Element 'at' stimmt immer noch nicht mit dem letzten Buchstaben der Zeichenfolge 't' überein.
Gehen Sie also noch ein Zeichen zurück.

4 Jetzt können wir das „a“ und das „t“ zuordnen.

5 Gehen Sie zum dritten Element '.*'. Da wir uns am Ende der Zeichenfolge befinden und '.*'
0-mal übereinstimmen, weisen Sie ihm die leere Zeichenfolge zu.

6 Wir sind fertig!

Meistens geschieht all dieses Vorwärts- und Zurückgehen schnell und die Suche
ist schnell. Es gibt jedoch einige pathologische Regexps, deren Ausführungszeit exponentiell
wächst mit der Größe der Saite. Eine typische Struktur, die einem um die Ohren fliegt, ist
die Form

/(a|b+)*/;

Das Problem sind die verschachtelten unbestimmten Quantifizierer. Es gibt viele verschiedene Möglichkeiten,
Aufteilung einer Zeichenfolge der Länge n zwischen "+" und "*": eine Wiederholung mit "b+" von
Länge n, zwei Wiederholungen mit der ersten "b+" Länge k und der zweiten mit Länge nk, m
Wiederholungen, deren Bits sich zu Länge n addieren, usw. Tatsächlich gibt es eine exponentielle Zahl
Möglichkeiten, einen String als Funktion seiner Länge zu partitionieren. Ein regulärer Ausdruck kann Glück haben und
Übereinstimmung früh im Prozess, aber wenn es keine Übereinstimmung gibt, versucht Perl alles, Möglichkeit
bevor Sie aufgeben. Seien Sie also vorsichtig mit verschachtelten "*", "{n,m}" und "+". Das Buch
Mastering Normale Ausdrücke von Jeffrey Friedl gibt eine wunderbare Diskussion darüber und
andere Effizienzprobleme.

besitzergreifend Quantifizierer
Das Zurückverfolgen während der unermüdlichen Suche nach einem Match kann Zeitverschwendung sein, insbesondere
wenn die Übereinstimmung zwangsläufig fehlschlägt. Betrachten Sie das einfache Muster

/^\w+\s+\w+$/; # ein Wort, Leerzeichen, ein Wort

Immer wenn dies auf eine Zeichenfolge angewendet wird, die nicht ganz den Erwartungen des Musters entspricht
wie "abc " oder "abc def ", wird die Regex-Engine zurückverfolgen, etwa einmal für
jedes Zeichen in der Zeichenfolge. Aber wir wissen, dass es keinen Weg gibt, alle
Anfangswortzeichen, die mit der ersten Wiederholung übereinstimmen, alle Räume müssen gegessen werden von
der Mittelteil, und dasselbe gilt für das zweite Wort.

Mit der Einführung des besitzergreifend Quantifizierer in Perl 5.10 haben wir eine Möglichkeit,
Anweisung an die Regex-Engine, nicht zurückzuverfolgen, mit den üblichen Quantifizierern mit einem "+"
angehängt. Das macht sie gierig und geizig; wenn sie einmal Erfolg haben, werden sie nicht
etwas zurückgeben, um eine andere Lösung zu ermöglichen. Sie haben folgende Bedeutung:

· "a{n,m}+" bedeutet: mindestens "n"-mal, höchstens "m"-mal, so oft wie
möglich, und geben Sie nichts auf. "a?+" ist die Abkürzung für "a{0,1}+"

· "a{n,}+" bedeutet: mindestens "n" mal, aber so oft wie möglich übereinstimmen, und nicht
gib nichts auf. „a*+“ ist die Abkürzung für „a{0,}+“ und „a++“ ist die Abkürzung für „a{1,}+“.

· "a{n}+" bedeutet: genau "n"-mal übereinstimmen. Es dient lediglich der Konsistenz der Notation.

Diese Possessivquantifikatoren stellen einen Sonderfall eines allgemeineren Konzepts dar, nämlich des
unabhängig Teilausdruck, siehe unten.

Als Beispiel für die Eignung eines Possessivquantifikators betrachten wir die Übereinstimmung eines zitierten
Zeichenfolge, wie sie in verschiedenen Programmiersprachen vorkommt. Der Backslash wird als
Escape-Zeichen, das angibt, dass das nächste Zeichen wörtlich genommen werden soll, als
ein weiteres Zeichen für die Zeichenfolge. Daher erwarten wir nach dem öffnenden Anführungszeichen ein
(möglicherweise leere) Folge von Alternativen: entweder ein beliebiges Zeichen außer einem Anführungszeichen ohne Escapezeichen
oder Backslash oder ein Escape-Zeichen.

/"(?:[^"\\]++|\\.)*+"/;

zum a regexp
An diesem Punkt haben wir alle grundlegenden Regexp-Konzepte abgedeckt, also lassen Sie uns einen genaueren
Beispiel für einen regulären Ausdruck. Wir erstellen einen regulären Ausdruck, der Zahlen abgleicht.

Die erste Aufgabe beim Erstellen eines regulären Ausdrucks besteht darin, zu entscheiden, was wir abgleichen möchten und was wir
Ausschließen. In unserem Fall wollen wir sowohl Ganzzahlen als auch Gleitkommazahlen abgleichen und wir
Sie möchten alle Zeichenfolgen ablehnen, die keine Zahlen sind.

Die nächste Aufgabe besteht darin, das Problem in kleinere Probleme zu zerlegen, die leicht umgewandelt werden können
in einen regulären Ausdruck.

Der einfachste Fall sind Ganzzahlen. Diese bestehen aus einer Ziffernfolge mit einer optionalen
Zeichen vor. Die Ziffern können wir mit "\d+" darstellen und das Zeichen kann mit
"[+-]". Somit ist der ganzzahlige reguläre Ausdruck

/[+-]?\d+/; # entspricht Ganzzahlen

Eine Gleitkommazahl hat möglicherweise ein Vorzeichen, einen ganzzahligen Teil, einen Dezimalpunkt, einen
Bruchteil und einen Exponenten. Einer oder mehrere dieser Teile sind optional, daher müssen wir
Schauen Sie sich die verschiedenen Möglichkeiten an. Gleitkommazahlen, die in der richtigen Form vorliegen
gehören 123, 0.345, 34, -1e6 und 25.4E-72. Wie bei ganzen Zahlen ist das Vorzeichen
völlig optional und kann durch "[+-]?" abgeglichen werden. Wir können sehen, dass, wenn es keine
Exponent, Gleitkommazahlen müssen einen Dezimalpunkt haben, sonst sind sie ganze Zahlen.
Wir könnten versucht sein, diese mit "\d*\.\d*" zu modellieren, aber dies würde auch nur einem
einzelne Dezimalstelle, die keine Zahl ist. Die drei Fälle von Gleitkommazahlen
ohne Exponent sind

/[+-]?\d+\./; # 1., 321. usw.
/[+-]?\.\d+/; # .1, .234 usw.
/[+-]?\d+\.\d+/; # 1.0, 30.56 usw.

Diese können mit einer dreifachen Abwechslung zu einem einzigen regulären Ausdruck kombiniert werden:

/[+-]?(\d+\.\d+|\d+\.|\.\d+)/; # Gleitkomma, kein Exponent

Bei dieser Abwechslung ist es wichtig, '\d+\.\d+' vor '\d+\.' zu setzen. Wenn '\d+\.'
Erstens würde der reguläre Ausdruck problemlos damit übereinstimmen und den Bruchteil der Zahl ignorieren.

Betrachten wir nun Gleitkommazahlen mit Exponenten. Die wichtigste Beobachtung hierbei ist, dass beide
Ganzzahlen und Zahlen mit Dezimalpunkt sind vor einem Exponenten erlaubt. Dann
Exponenten sind, wie das Gesamtzeichen, unabhängig davon, ob wir Zahlen mit
oder ohne Dezimalpunkte und kann von der Mantisse 'entkoppelt' werden. Die Gesamtform von
der reguläre Ausdruck wird nun klar:

/^(optionales Vorzeichen)(Ganzzahl | fp-Mantisse)(optionaler Exponent)$/;

Der Exponent ist ein "e" oder "E", gefolgt von einer Ganzzahl. Der Exponenten-Regex lautet also

/[eE][+-]?\d+/; # Exponent

Wenn wir alle Teile zusammenfügen, erhalten wir einen regulären Ausdruck, der mit Zahlen übereinstimmt:

/^[+-]?(\d+\.\d+|\d+\.|\.\d+|\d+)([eE][+-]?\d+)?$/; # Ta da!

Lange reguläre Ausdrücke wie diese mögen Ihre Freunde beeindrucken, können aber schwer zu entziffern sein. In komplexen
In solchen Situationen ist der Modifikator "//x" für eine Übereinstimmung von unschätzbarem Wert. Er ermöglicht es,
nahezu beliebige Leerzeichen und Kommentare in einen regulären Ausdruck, ohne deren Bedeutung zu beeinflussen.
Damit können wir unseren 'erweiterten' regulären Ausdruck in die ansprechendere Form umschreiben

/^
[+-]? # zuerst ein optionales Zeichen abgleichen
( # dann ganze Zahlen oder fp-Mantissen abgleichen:
\d+\.\d+ # Mantisse der Form ab
|\d+\. # Mantisse der Form a.
|\.\d+ # Mantisse der Form .b
|\d+ # Ganzzahl der Form a
)
([eE][+-]?\d+)? # schließlich optional einen Exponenten abgleichen
$/x;

Wenn Leerzeichen größtenteils irrelevant sind, wie fügt man Leerzeichen in eine erweiterte
Regulärer Ausdruck? Die Antwort ist, ihn mit einem Backslash '\ ' zu versehen oder ihn in eine Zeichenklasse "[ ]" zu setzen. Dasselbe
Das Gleiche gilt für Rautenzeichen: Verwenden Sie "\#" oder "[#]". Perl erlaubt beispielsweise ein Leerzeichen zwischen
das Vorzeichen und die Mantisse oder Ganzzahl, und wir könnten dies unserem regulären Ausdruck wie folgt hinzufügen:

/^
[+-]?\ * # zuerst ein optionales Zeichen *und Leerzeichen* abgleichen
( # dann ganze Zahlen oder fp-Mantissen abgleichen:
\d+\.\d+ # Mantisse der Form ab
|\d+\. # Mantisse der Form a.
|\.\d+ # Mantisse der Form .b
|\d+ # Ganzzahl der Form a
)
([eE][+-]?\d+)? # schließlich optional einen Exponenten abgleichen
$/x;

In dieser Form ist es einfacher, eine Möglichkeit zur Vereinfachung des Wechsels zu erkennen. Alternativen 1, 2,
und 4 beginnen alle mit „\d+“, also könnte es herausgerechnet werden:

/^
[+-]?\ * # zuerst ein optionales Zeichen abgleichen
( # dann ganze Zahlen oder fp-Mantissen abgleichen:
\d+ # beginne mit einem ...
(
\.\d* # Mantisse der Form ab oder a.
)? # ? kümmert sich um Ganzzahlen der Form a
|\.\d+ # Mantisse der Form .b
)
([eE][+-]?\d+)? # schließlich optional einen Exponenten abgleichen
$/x;

oder in der Kompaktform geschrieben,

/^[+-]?\ *(\d+(\.\d*)?|\.\d+)([eE][+-]?\d+)?$/;

Dies ist unser endgültiger regulärer Ausdruck. Um es noch einmal zusammenzufassen: Wir haben einen regulären Ausdruck erstellt, indem wir

· die Aufgabenstellung detailliert zu spezifizieren,

· das Problem in kleinere Teile zu zerlegen,

· die Übersetzung der Kleinteile in reguläre Ausdrücke,

· Kombinieren der regulären Ausdrücke,

· und Optimierung des endgültigen kombinierten regulären Ausdrucks.

Dies sind auch die typischen Schritte beim Schreiben eines Computerprogramms. Dies macht
perfekten Sinn, denn reguläre Ausdrücke sind im Wesentlichen Programme, die in einem kleinen
Computersprache, die Muster spezifiziert.

Die richtigen regulär Ausdrücke in Perl
Das letzte Thema von Teil 1 behandelt kurz die Verwendung von Regexps in Perl-Programmen. Wo
passen sie in die Perl-Syntax?

Wir haben den Matching-Operator bereits in seiner Standardeinstellung "/regexp/" und beliebig eingeführt
Trennzeichen "m!regexp!" bildet. Wir haben den Bindungsoperator "=~" und seine Negation "!~" verwendet
um auf Übereinstimmungen zu prüfen. Im Zusammenhang mit dem Matching-Operator haben wir die
einzeilige „//s“, mehrzeilige „//m“, Groß-/Kleinschreibung ignorierende „//i“- und erweiterte „//x“-Modifikatoren.
Es gibt noch ein paar weitere Dinge, die Sie über Matching-Operatoren wissen sollten.

Verbot Substitution

Wenn Sie $pattern nach der ersten Ersetzung ändern, wird Perl dies ignorieren. Wenn Sie
Wenn Sie überhaupt keine Ersetzungen wünschen, verwenden Sie das spezielle Trennzeichen „m“:

@pattern = ('Seuss');
während (<>) {
print if m'@pattern'; # entspricht wörtlichem '@pattern', nicht 'Seuss'
}

Ähnlich wie bei Zeichenfolgen fungiert "m''" als Apostroph in einem regulären Ausdruck; alle anderen "m"-Trennzeichen fungieren
wie Anführungszeichen. Wenn der reguläre Ausdruck eine leere Zeichenfolge ergibt, wird der reguläre Ausdruck in der letzte
erfolgreich Spiel wird stattdessen verwendet. Wir haben also

"dog" =~ /d/; # 'd'-Übereinstimmungen
"dogbert =~ //; # dies entspricht dem zuvor verwendeten regulären Ausdruck 'd'

Global Abstimmung

Die letzten beiden Modifikatoren, die wir hier besprechen, „//g“ und „//c“, betreffen mehrere Übereinstimmungen.
Der Modifikator "//g" steht für globales Matching und ermöglicht dem Matching-Operator das Matching
innerhalb einer Zeichenfolge so oft wie möglich. Im Skalarkontext werden aufeinanderfolgende Aufrufe
gegen eine Zeichenfolge wird "//g" von Übereinstimmung zu Übereinstimmung springen, die Position in
die Zeichenfolge, während sie verläuft. Sie können die Position mit der Funktion "pos()" abrufen oder festlegen.

Die Verwendung von "//g" wird im folgenden Beispiel gezeigt. Angenommen, wir haben eine Zeichenfolge, die
besteht aus Wörtern, die durch Leerzeichen getrennt sind. Wenn wir im Voraus wissen, wie viele Wörter es gibt,
könnte die Wörter mithilfe von Gruppierungen extrahieren:

$x = "Katzenhundehütte"; # 3 Wörter
$x =~ /^\s*(\w+)\s+(\w+)\s+(\w+)\s*$/; # Übereinstimmungen,
# $1 = 'Katze'
# $2 = 'Hund'
# $3 = 'Haus'

Aber was wäre, wenn wir eine unbestimmte Anzahl von Wörtern hätten? Dies ist die Art von Aufgabe, die "//g" war
gemacht für. Um alle Wörter zu extrahieren, bilden Sie den einfachen regulären Ausdruck "(\w+)" und durchlaufen Sie alle Übereinstimmungen
mit "/(\w+)/g":

während ($x =~ /(\w+)/g) {
print "Wort ist $1, endet an Position", pos $x, "\n";
}

Drucke

Wort ist Katze, endet an Position 3
Wort ist Hund, endet an Position 7
Wort ist Haus, endet an Position 13

Eine fehlgeschlagene Übereinstimmung oder das Ändern der Zielzeichenfolge setzt die Position zurück. Wenn du das nicht willst
Position nach fehlgeschlagener Übereinstimmung zurückgesetzt wird, fügen Sie "//c" hinzu, wie in "/regexp/gc". Die aktuelle
Position in der Zeichenfolge ist mit der Zeichenfolge verknüpft, nicht mit dem regulären Ausdruck. Dies bedeutet, dass
Verschiedene Saiten haben unterschiedliche Positionen und ihre jeweiligen Positionen können eingestellt werden oder
selbstständig lesen.

Im Listenkontext gibt "//g" eine Liste mit übereinstimmenden Gruppierungen zurück, oder wenn keine Gruppierungen vorhanden sind,
eine Liste von Übereinstimmungen mit dem gesamten regulären Ausdruck. Wenn wir also nur die Wörter wollten, könnten wir

@words = ($x =~ /(\w+)/g); # Streichhölzer,
# $words[0] = 'Katze'
# $words[1] = 'Hund'
# $words[2] = 'Haus'

Eng verbunden mit dem Modifikator "//g" ist der Anker "\G". Der Anker "\G" entspricht
an der Stelle, an der die vorherige Übereinstimmung mit "//g" endete. "\G" ermöglicht uns, einfach Kontext-
sensibles Matching:

$metric = 1; # metrische Einheiten verwenden
...
$x = ; # Messwert einlesen
$x =~ /^([+-]?\d+)\s*/g; # Größe ermitteln
$Gewicht = $1;
if ($metric) { # Fehlerprüfung
drucke "Einheitenfehler!", es sei denn, $x =~ /\Gkg\./g;
}
else {
drucke "Einheitenfehler!", es sei denn, $x =~ /\Glbs\./g;
}
$x =~ /\G\s+(widget|sprocket)/g; # Verarbeitung fortsetzen

Die Kombination von "//g" und "\G" ermöglicht es uns, die Zeichenfolge Stück für Stück zu verarbeiten und
beliebige Perl-Logik, um zu entscheiden, was als nächstes zu tun ist. Derzeit ist der "\G"-Anker nur vollständig
wird unterstützt, wenn es zum Verankern am Anfang des Musters verwendet wird.

"\G" ist auch bei der Verarbeitung von Datensätzen mit fester Länge und regulären Ausdrücken von unschätzbarem Wert. Angenommen, wir haben
ein Ausschnitt der codierenden Region DNA, kodiert als Basenpaarbuchstaben "ATCGTTGAAT..." und wir wollen
um alle Stopcodons "TGA" zu finden. In einer codierenden Region sind Codons 3-Buchstaben-Sequenzen, also
Wir können uns den DNA-Schnipsel als eine Folge von 3-Buchstaben-Datensätzen vorstellen. Der naive reguläre Ausdruck

# erweitert, dies ist „ATC GTT GAA TGC AAA TGA CAT GAC“
$dna = "ATCGTTGAATGCAAATGACATGAC";
$dna =~ /TGA/;

funktioniert nicht; es kann mit einem "TGA" übereinstimmen, aber es gibt keine Garantie dafür, dass die Übereinstimmung ausgerichtet ist
mit Codongrenzen, z. B. ergibt die Teilzeichenfolge "GTT GAA" eine Übereinstimmung. Eine bessere Lösung ist

während ($dna =~ /(\w\w\w)*?TGA/g) { # beachte das minimale *?
print "Habe ein TGA-Stopcodon an Position ", pos $dna, "\n";
}

welche druckt

Habe ein TGA-Stopcodon an Position 18
Habe ein TGA-Stopcodon an Position 23

Position 18 ist gut, aber Position 23 ist falsch. Was ist passiert?

Die Antwort ist, dass unser regulärer Ausdruck gut funktioniert, bis wir die letzte echte Übereinstimmung hinter uns haben. Dann
Der reguläre Ausdruck kann nicht mit einem synchronisierten „TGA“ übereinstimmen und beginnt, ein Zeichen weiterzugehen
Position zu einer Zeit, nicht das, was wir wollen. Die Lösung ist, "\G" zu verwenden, um die Übereinstimmung zu verankern
die Codon-Ausrichtung:

während ($dna =~ /\G(\w\w\w)*?TGA/g) {
print "Habe ein TGA-Stopcodon an Position ", pos $dna, "\n";
}

Dies wird gedruckt

Habe ein TGA-Stopcodon an Position 18

welches die richtige Antwort ist. Dieses Beispiel zeigt, dass es wichtig ist, nicht nur
dem Gewünschten zu entsprechen, aber das Unerwünschte abzulehnen.

(Es gibt noch andere Regexp-Modifikatoren, wie z. B. "//o", aber ihre speziellen
Verwendungsmöglichkeiten gehen über den Rahmen dieser Einführung hinaus.)

Suche und ersetzen

Reguläre Ausdrücke spielen auch eine große Rolle in search und ersetzen Operationen in Perl. Suche
und Ersetzen erfolgt mit dem Operator "s///". Die allgemeine Form ist
"s/regexp/replacement/modifiers", mit allem, was wir über reguläre Ausdrücke und Modifikatoren wissen
Dies gilt auch in diesem Fall. Der "Ersatz" ist eine Perl-Zeichenfolge in doppelten Anführungszeichen, die
ersetzt im String alles, was mit dem "regexp" übereinstimmt. Der Operator "=~" ist auch
Wird hier verwendet, um eine Zeichenfolge mit "s///" zu verknüpfen. Bei Übereinstimmung mit $_ kann "$_ =~"
gelöscht. Wenn eine Übereinstimmung vorliegt, gibt "s///" die Anzahl der vorgenommenen Ersetzungen zurück; andernfalls
es gibt false zurück. Hier sind einige Beispiele:

$x = "Zeit, die Katze zu füttern!";
$x =~ s/cat/hacker/; # $x enthält "Zeit, den Hacker zu füttern!"
wenn ($x =~ s/^(Zeit.*Hacker)!$/$1 jetzt!/) {
$more_insistent = 1;
}
$y = "'zitierte Wörter'";
$y =~ s/^'(.*)'$/$1/; # einfache Anführungszeichen entfernen,
# $y enthält "zitierte Wörter"

Im letzten Beispiel wurde die ganze Zeichenfolge gefunden, aber nur der Teil innerhalb der einzelnen
Anführungszeichen gruppiert wurden. Mit dem Operator "s///" werden die übereinstimmenden Variablen $1, $2 usw.
sofort für den Einsatz im Ersetzungsausdruck verfügbar, also verwenden wir $1, um die
zitierten String mit genau dem, was zitiert wurde. Mit dem globalen Modifikator "s///g" wird gesucht
und ersetzen Sie alle Vorkommen des regulären Ausdrucks in der Zeichenfolge:

$x = "Ich habe 4 für 4 geschlagen";
$x =~ s/4/four/; # macht nicht alles:
# $x enthält „Ich habe vier für 4 geschlagen“
$x = "Ich habe 4 für 4 geschlagen";
$x =~ s/4/four/g; # macht alles:
# $x enthält „Ich habe vier von vier geschlagen“

Wenn Sie in diesem Tutorial 'regex' gegenüber 'regexp' bevorzugen, können Sie das folgende Programm verwenden
um es zu ersetzen:

% Katze > simple_replace
#!/ Usr / bin / perl
$regexp = Verschiebung;
$Ersatz = Verschiebung;
während (<>) {
s/$regulärer Ausdruck/$Ersatz/g;
drucken;
}
^D

% simple_replace regulärer Ausdruck regulärer Ausdruck perlretut.pod

In "simple_replace" haben wir den Modifikator "s///g" verwendet, um alle Vorkommen des regulären Ausdrucks zu ersetzen
in jeder Zeile. (Obwohl der reguläre Ausdruck in einer Schleife erscheint, ist Perl intelligent genug
um es nur einmal zu kompilieren.) Wie bei "simple_grep" sind sowohl die "print"- als auch die
„s/$regexp/$replacement/g“ verwendet implizit $_.

Wenn Sie nicht möchten, dass "s///" Ihre ursprüngliche Variable ändert, können Sie die zerstörungsfreie
Ersatzmodifikator, "s///r". Dies ändert das Verhalten so, dass "s///r" die endgültige
ersetzte Zeichenfolge (anstelle der Anzahl der Ersetzungen):

$x = "Ich mag Hunde.";
$y = $x =~ s/Hunde/Katzen/r;
drucke "$x $y\n";

Dieses Beispiel gibt "Ich mag Hunde. Ich mag Katzen" aus. Beachten Sie, dass die ursprüngliche Variable $x
nicht beeinflusst. Das Gesamtergebnis der Ersetzung wird stattdessen in $y gespeichert. Wenn die
Die Ersetzung hat keine Auswirkungen, dann wird die ursprüngliche Zeichenfolge zurückgegeben:

$x = "Ich mag Hunde.";
$y = $x =~ s/Elefanten/Pumas/r;
print "$x $y\n"; # druckt "Ich mag Hunde. Ich mag Hunde."

Eine weitere interessante Sache, die das Flag „s///r“ ermöglicht, ist die Verkettung von Ersetzungen:

$x = "Katzen sind toll.";
print $x =~ s/Katzen/Hunde/r =~ s/Hunde/Frösche/r =~
s/Frösche/Igel/r, "\n";
# druckt "Igel sind toll."

Ein speziell für Suchen und Ersetzen verfügbarer Modifikator ist die Auswertung "s///e"
Modifikator. "s///e" behandelt den Ersetzungstext als Perl-Code und nicht als doppelte Anführungszeichen
Zeichenfolge. Der vom Code zurückgegebene Wert wird durch die übereinstimmende Teilzeichenfolge ersetzt.
„s///e“ ist nützlich, wenn Sie beim Ersetzen von Text einige Berechnungen durchführen müssen.
Dieses Beispiel zählt die Zeichenhäufigkeiten in einer Zeile:

$x = "Bill, die Katze";
$x =~ s/(.)/$chars{$1}++;$1/eg; # final $1 ersetzt char durch sich selbst
print "Häufigkeit von '$_' ist $chars{$_}\n"
foreach (sortiere {$chars{$b} <=> $chars{$a}} Schlüssel %chars);

Dies wird gedruckt

Häufigkeit von ' ' ist 2
Die Häufigkeit von 't' beträgt 2
Die Häufigkeit von 'l' beträgt 2
Häufigkeit von 'B' ist 1
Die Häufigkeit von 'c' beträgt 1
Die Frequenz von 'e' ist 1
Die Häufigkeit von 'h' ist 1
Die Häufigkeit von 'i' ist 1
Die Häufigkeit von 'a' ist 1

Wie beim Übereinstimmungsoperator „m//“ können für „s///“ andere Trennzeichen verwendet werden, wie etwa „s!!!“ und
"s{}{}" und sogar "s{}//". Wenn einfache Anführungszeichen verwendet werden "s'''", dann der reguläre Ausdruck und
Ersetzungen werden als Zeichenfolgen in einfachen Anführungszeichen behandelt und es gibt keine Variablenersetzungen.
"s///" im Listenkontext gibt dasselbe zurück wie im Skalarkontext, nämlich die Anzahl der
Streichhölzer.

Die gespalten Funktion

Die Funktion „split()“ ist eine weitere Stelle, an der ein regulärer Ausdruck verwendet wird. „split /regexp/, string,
„Limit“ trennt den Operanden „String“ in eine Liste von Teilstrings und gibt diese Liste zurück.
Der reguläre Ausdruck muss so gestaltet sein, dass er mit den Trennzeichen für die gewünschte
Teilzeichenfolgen. Das "Limit", falls vorhanden, beschränkt die Aufteilung in nicht mehr als "Limit"
Anzahl der Zeichenfolgen. Um beispielsweise eine Zeichenfolge in Wörter aufzuteilen, verwenden Sie

$x = "Calvin und Hobbes";
@words = split /\s+/, $x; # $word[0] = 'Calvin'
# $word[1] = 'und'
# $word[2] = 'Hobbes'

Wenn der leere reguläre Ausdruck "//" verwendet wird, stimmt der reguläre Ausdruck immer überein und die Zeichenfolge wird aufgeteilt in
einzelne Zeichen. Wenn der reguläre Ausdruck Gruppierungen hat, dann enthält die resultierende Liste die
auch passende Teilstrings aus den Gruppierungen. Zum Beispiel

$x = "/ Usr / bin / perl";
@dirs = split m!/!, $x; # $dirs[0] = ''
# $dirs[1] = 'usr'
# $dirs[2] = 'bin'
# $dirs[3] = 'perl'
@parts = m teilen!(/)!, $x; # $teile[0] = ''
# $teile[1] = '/'
# $parts[2] = 'usr'
# $teile[3] = '/'
# $parts[4] = 'bin'
# $teile[5] = '/'
# $parts[6] = 'perl'

Da das erste Zeichen von $x mit dem regulären Ausdruck übereinstimmte, wurde "split" ein leeres Initial vorangestellt
Element in die Liste.

Wenn Sie bis hierhin gelesen haben, herzlichen Glückwunsch! Sie verfügen nun über alle grundlegenden Werkzeuge, die Sie benötigen, um
reguläre Ausdrücke zur Lösung einer Vielzahl von Textverarbeitungsproblemen. Wenn dies Ihr
Wenn Sie das Tutorial zum ersten Mal durchgehen, warum hören Sie nicht hier auf und spielen mit regulären Ausdrücken herum?
während.... Teil 2 befasst sich mit den esoterischeren Aspekten regulärer Ausdrücke und denen
Konzepte sind sicher nicht gleich zu Beginn erforderlich.

Teil 2: Strom Werkzeuge


OK, Sie kennen die Grundlagen von Regexps und möchten mehr erfahren. Wenn reguläre Ausdrücke übereinstimmen
Ausdrücke ist analog zu einem Spaziergang im Wald, dann sind die Werkzeuge, die in Teil 1 besprochen werden
analog zu topografischen Karten und einem Kompass, grundlegende Werkzeuge, die wir ständig benutzen. Die meisten Werkzeuge
in Teil 2 sind analog zu Leuchtpistolen und Satellitentelefonen. Sie werden nicht allzu oft verwendet auf
eine Wanderung, aber wenn wir nicht weiterkommen, können sie von unschätzbarem Wert sein.

Im Folgenden sind die fortgeschritteneren, weniger genutzten oder manchmal esoterischen Fähigkeiten von Perl aufgeführt.
Reguläre Ausdrücke. In Teil 2 gehen wir davon aus, dass Sie mit den Grundlagen vertraut sind und konzentrieren uns auf
die erweiterten Funktionen.

Mehr on Figuren, Streicher, und Charakter Unterricht
Es gibt eine Reihe von Escape-Sequenzen und Zeichenklassen, die wir noch nicht behandelt haben.

Es gibt mehrere Escape-Sequenzen, die Zeichen oder Zeichenfolgen zwischen Groß- und Kleinschreibung konvertieren.
Kleinbuchstaben und sie sind auch innerhalb von Mustern verfügbar. "\l" und "\u" konvertieren die nächsten
Zeichen in Klein- bzw. Großbuchstaben:

$x = "Perl";
$string =~ /\u$x/; # entspricht 'Perl' in $string
$x = "M(rs?|s)\\."; # beachte den doppelten Backslash
$string =~ /\l$x/; # entspricht „mr.“, „mrs.“ und „ms.“,

Ein "\L" oder "\U" zeigt eine dauerhafte Umwandlung der Groß-/Kleinschreibung an, bis sie durch "\E" beendet oder
durch ein anderes "\U" oder "\L" ersetzt:

$x = "Dieses Wort ist klein geschrieben:\L SHOUT\E";
$x =~ /shout/; # Übereinstimmungen
$x = „ICH STECHE IMMER NOCH KARTEN FÜR MEINE 360“
$x =~ /\Ukeypunch/; # entspricht der Lochkartenzeichenfolge

Wenn kein "\E" vorhanden ist, wird die Groß-/Kleinschreibung bis zum Ende des Strings geändert. Die regulären Ausdrücke
"\L\u$word" oder "\u\L$word" wandelt das erste Zeichen von $word in Großbuchstaben um und den Rest
der Zeichen in Kleinbuchstaben.

Steuerzeichen können mit "\c" maskiert werden, so dass ein Control-Z-Zeichen
mit "\cZ" abgeglichen. Die Escape-Sequenz "\Q"..."\E" zitiert oder schützt die meisten nicht-
alphabetische Zeichen. Zum Beispiel

$x = "\QDas !^*&%~& Katze!";
$x =~ /\Q!^*&%~&\E/; # auf grobe Sprache prüfen

Es schützt weder "$" noch "@", sodass Variablen weiterhin ersetzt werden können.

"\Q", "\L", "\l", "\U", "\u" und "\E" sind eigentlich Teil der doppelten Anführungszeichen-Syntax und nicht
Teil der eigentlichen Regexp-Syntax. Sie funktionieren, wenn sie in einem regulären Ausdruck erscheinen
direkt in ein Programm eingebettet, aber nicht, wenn es in einer Zeichenfolge enthalten ist, die interpoliert wird in
ein Muster.

Perl-Regexps können mehr als nur den Standard-ASCII-Zeichensatz verarbeiten. Perl unterstützt
Unicode, ein Standard zur Darstellung der Alphabete aus praktisch allen Teilen der Welt
geschriebene Sprachen und eine Vielzahl von Symbolen. Perls Textzeichenfolgen sind Unicode-Zeichenfolgen, also
Sie können Zeichen mit einem Wert (Codepunkt oder Zeichennummer) größer als 255 enthalten.

Was bedeutet das für reguläre Ausdrücke? Nun, Regexp-Benutzer müssen nicht viel über Perls
interne Darstellung von Zeichenfolgen. Aber sie müssen wissen, 1) wie Unicode dargestellt wird
Zeichen in einem regulären Ausdruck und 2) dass eine Matching-Operation die Zeichenfolge als
als Zeichenfolge gesucht, nicht als Bytes. Die Antwort auf 1) ist, dass Unicode
Zeichen größer als "chr(255)" werden mit der Notation "\x{hex}" dargestellt, weil
\x hex (ohne geschweifte Klammern) geht nicht über 255 hinaus. (Ab Perl 5.14, wenn
Wenn Sie ein Oktal-Fan sind, können Sie auch "\o{oct}" verwenden.)

/\x{263a}/; # entspricht einem Unicode-Smiley :)

HINWEIS: In Perl 5.6.0 musste man früher "use utf8" sagen, um Unicode zu verwenden
Funktionen. Dies ist nicht mehr der Fall: Für fast die gesamte Unicode-Verarbeitung ist die explizite
Das Pragma "utf8" wird nicht benötigt. (Es ist nur dann wichtig, wenn Ihr Perl-Skript in
Unicode und in UTF-8 kodiert, dann ist ein explizites „use utf8“ erforderlich.)

Herausfinden der hexadezimalen Sequenz eines gewünschten Unicode-Zeichens oder Entschlüsseln
jemand anderes hexadezimalen Unicode-Regexp ist etwa so viel Spaß wie das Programmieren in Maschine
Code. Eine weitere Möglichkeit, Unicode-Zeichen anzugeben, ist die Verwendung des namens Charakter Flucht
Sequenz "\N{Name}". Name ist ein Name für das Unicode-Zeichen, wie in der
Unicode-Standard. Wenn wir zum Beispiel das Sternzeichen darstellen oder abgleichen wollten
Für den Planeten Merkur könnten wir verwenden

$x = "abc\N{MERCURY}def";
$x =~ /\N{MERCURY}/; # Übereinstimmungen

Man kann auch „kurze“ Namen verwenden:

print "\N{GRIECHISCHER KLEINBUCHSTABE SIGMA} heißt Sigma.\n";
print "\N{greek:Sigma} ist ein Sigma in Großbuchstaben.\n";

Sie können Namen auch auf ein bestimmtes Alphabet beschränken, indem Sie das Pragma „charnames“ angeben:

verwenden Sie die Zeichennamen qw (griechisch);
print "\N{sigma} ist griechisches Sigma\n";

Ein Index der Zeichennamen ist online beim Unicode-Konsortium verfügbar.
<http://www.unicode.org/charts/charindex.html>; erklärendes Material mit Links zu anderen
Ressourcen beihttp://www.unicode.org/standard/where>.

Die Antwort auf Anforderung 2) ist, dass ein regulärer Ausdruck (meistens) Unicode-Zeichen verwendet. Die
"mostly" ist aus Gründen der unübersichtlichen Abwärtskompatibilität, aber ab Perl 5.14, jeder reguläre Ausdruck
kompiliert im Rahmen eines "use feature 'unicode_strings'" (das automatisch aktiviert wird
im Rahmen einer "use 5.012" oder höher) wird aus "meistens" "immer". Wenn
Wenn Sie Unicode korrekt verarbeiten möchten, sollten Sie sicherstellen, dass 'unicode_strings' aktiviert ist
an. Intern wird dies entweder mit UTF-8 oder einer nativen 8-Bit-Kodierung in Bytes kodiert,
abhängig von der Geschichte der Zeichenfolge, aber konzeptionell ist es eine Folge von Zeichen,
nicht Bytes. Ein Tutorial dazu finden Sie unter perlunitut.

Lassen Sie uns nun die Unicode-Zeichenklassen besprechen, die üblicherweise als „Zeicheneigenschaften“ bezeichnet werden.
Diese werden durch die Escape-Sequenz "\p{name}" dargestellt. Eng damit verbunden ist die
Die Eigenschaft "\P{name}", die die Negation der Eigenschaft "\p{name}" darstellt. Um beispielsweise
Klein- und Großbuchstaben,

$x = "BOB";
$x =~ /^\p{IsUpper}/; # Übereinstimmungen, Großbuchstaben-Char-Klasse
$x =~ /^\P{IsUpper}/; # stimmt nicht überein, Zeichenklasse ohne Großbuchstaben
$x =~ /^\p{IsLower}/; # stimmt nicht überein, Kleinbuchstaben-Char-Klasse
$x =~ /^\P{IsLower}/; # Übereinstimmungen, Zeichenklasse ohne Kleinbuchstaben

(Das „Ist“ ist optional.)

Es gibt unzählige Unicode-Zeicheneigenschaften. Die vollständige Liste finden Sie unter perluniprops.
Die meisten von ihnen haben Synonyme mit kürzeren Namen, die ebenfalls dort aufgeführt sind. Einige Synonyme sind
einzelnes Zeichen. Hierfür können Sie die Klammern weglassen. Beispielsweise ist "\pM" dasselbe
so etwas wie "\p{Mark}", also Dinge wie Akzentzeichen.

Die Unicode-Eigenschaft "\p{Script}" wird verwendet, um jedes Unicode-Zeichen in die
Sprache, in der es geschrieben ist. Zum Beispiel Englisch, Französisch und eine Reihe anderer
Die europäischen Sprachen werden in lateinischer Schrift geschrieben. Es gibt aber auch die griechische Schrift,
die Thai-Schrift, die Katakana-Schrift usw. Sie können testen, ob ein Zeichen in einer
bestimmte Schrift mit zum Beispiel "\p{Latin}", "\p{Greek}" oder "\p{Katakana}". Zum Testen
wenn es nicht in balinesischer Schrift ist, verwenden Sie "\P{Balinese}".

Was wir bisher beschrieben haben, ist die einzige Form der Zeichenklasse "\p{...}".
Es gibt auch eine zusammengesetzte Form, die Ihnen möglicherweise begegnet. Diese sieht aus wie "\p{name=value}" oder
"\p{name:value}" (Gleichheitszeichen und Doppelpunkt können synonym verwendet werden). Diese sind
allgemeiner als die Einzelform, und tatsächlich sind die meisten Einzelformen einfach Perl-definiert
Abkürzungen für gängige zusammengesetzte Formen. Beispielsweise die Skriptbeispiele im vorherigen
Absatz könnte äquivalent geschrieben werden als "\p{Script=Latin}", "\p{Script:Greek}",
"\p{script=katakana}" und "\P{script=balinese}" (die Groß- und Kleinschreibung zwischen den "{}" spielt keine Rolle)
Klammern). Sie müssen die zusammengesetzten Formen vielleicht nie verwenden, aber manchmal ist es notwendig, und
Ihre Verwendung kann dazu beitragen, dass Ihr Code leichter verständlich wird.

"\X" ist eine Abkürzung für eine Zeichenklasse, die einen Unicode umfasst verlängert Graphem
Gruppe. Dies stellt ein „logisches Zeichen“ dar: was wie ein einzelnes Zeichen aussieht,
kann aber intern durch mehr als eine dargestellt werden. Beispielsweise kann die Verwendung des Unicode-Vollcodes
Namen, z. B. ist "A + COMBINING RING" ein Graphemcluster mit dem Basisbuchstaben "A" und
Kombinationszeichen "KOMBINATIONSRING", was auf Dänisch A mit dem Kreis darüber bedeutet
es, wie im Wort Aangstrom.

Vollständige und aktuelle Informationen zu Unicode finden Sie im neuesten Unicode-Standard oder im
Website des Unicode-Konsortiumshttp://www.unicode.org>

Als ob all diese Klassen nicht genug wären, definiert Perl auch Zeichenklassen im POSIX-Stil.
Diese haben die Form "[:name:]", wobei "name" der Name der POSIX-Klasse ist. Die POSIX
Klassen sind "Alpha", "Alnum", "ASCII", "Cntrl", "Digit", "Graph", "Lower", "Print",
"punct", "space", "upper" und "xdigit" sowie zwei Erweiterungen, "word" (eine Perl-Erweiterung für
entspricht "\w") und "blank" (eine GNU-Erweiterung). Der Modifikator "//a" beschränkt diese auf
nur im ASCII-Bereich übereinstimmen; ansonsten können sie mit den entsprechenden übereinstimmen
Perl Unicode-Klassen: "[:upper:]" ist dasselbe wie "\p{IsUpper}", usw. (Es gibt einige
Ausnahmen und Fallstricke dabei; siehe perlrecharclass für eine vollständige Diskussion.) Die
„[:digit:]“, „[:word:]“ und „[:space:]“ entsprechen den bekannten „\d“, „\w“ und „\s“.
Zeichenklassen. Um eine POSIX-Klasse zu negieren, setzen Sie ein "^" vor den Namen, so dass
Beispielsweise entspricht "[:^digit:]" "\D" und unter Unicode "\P{IsDigit}". Die Unicode- und
POSIX-Zeichenklassen können wie "\d" verwendet werden, mit der Ausnahme, dass POSIX
Zeichenklassen können nur innerhalb einer Zeichenklasse verwendet werden:

/\s+[abc[:digit:]xyz]\s*/; # entspricht a,b,c,x,y,z oder einer Ziffer
/^=item\s[[:digit:]]/; # entspricht '=item',
# gefolgt von einem Leerzeichen und einer Ziffer
/\s+[abc\p{IsDigit}xyz]\s+/; # entspricht a,b,c,x,y,z oder einer Ziffer
/^=item\s\p{IsDigit}/; # Übereinstimmung mit '=item',
# gefolgt von einem Leerzeichen und einer Ziffer

Puh! Das sind alle restlichen Charaktere und Charakterklassen.

Kompilieren und Einsparung regulär Ausdrücke
In Teil 1 haben wir erwähnt, dass Perl einen regulären Ausdruck in eine kompakte Folge von Operationscodes kompiliert.
Ein kompilierter regulärer Ausdruck ist also eine Datenstruktur, die einmal gespeichert und wieder verwendet werden kann und
wieder. Das Regexp-Anführungszeichen "qr//" macht genau das: "qr/string/" kompiliert den "String" als
regexp und wandelt das Ergebnis in eine Form um, die einer Variablen zugewiesen werden kann:

$reg = qr/foo+bar?/; # reg enthält einen kompilierten regulären Ausdruck

Dann kann $reg als regulärer Ausdruck verwendet werden:

$x = "fooooba";
$x =~ $reg; # Übereinstimmungen, genau wie /foo+bar?/
$x =~ /$reg/; # dasselbe, alternative Form

$reg kann auch in einen größeren regulären Ausdruck interpoliert werden:

$x =~ /(abc)?$reg/; # passt immer noch

Wie beim Matching-Operator können auch beim Regexp-Anführungszeichen verschiedene Trennzeichen verwendet werden, z. B.
"qr!!", "qr{}" oder "qr~~". Apostrophe als Trennzeichen ("qr''") verhindern jegliche Interpolation.

Vorkompilierte reguläre Ausdrücke sind nützlich, um dynamische Übereinstimmungen zu erstellen, die nicht
jedes Mal neu kompiliert, wenn sie auftreten. Mit vorkompilierten regulären Ausdrücken schreiben wir eine
"grep_step"-Programm, das nach einer Musterfolge sucht und zum nächsten Muster übergeht
sobald man zufrieden ist.

% Katze > grep_step
#!/ Usr / bin / perl
# grep_step - Übereinstimmung Reguläre Ausdrücke, einer nach dem anderen
# Verwendung: multi_grep regulärer Ausdruck1 regulärer Ausdruck2 ... Datei1 Datei2 ...

$Nummer = Verschiebung;
$regexp[$_] = Verschiebung für jeden (0..$Zahl-1);
@kompiliert = Karte qr/$_/, @regexp;
während ($Zeile = <>) {
wenn ($Zeile =~ /$kompiliert[0]/) {
drucke $zeile;
Verschiebung @kompiliert;
zuletzt, sofern nicht @kompiliert;
}
}
^D

% grep_step 3 shift drucke letzten grep_step
$Nummer = Verschiebung;
drucke $zeile;
zuletzt, sofern nicht @kompiliert;

Das Speichern vorkompilierter regulärer Ausdrücke in einem Array @compiled ermöglicht uns, einfach durch die
Reguläre Ausdrücke ohne Neukompilierung, wodurch Flexibilität gewonnen wird, ohne die Geschwindigkeit zu beeinträchtigen.

Komponieren regulär Ausdrücke at Laufzeit
Backtracking ist effizienter als wiederholte Versuche mit verschiedenen regulären Ausdrücken. Wenn
Es gibt mehrere reguläre Ausdrücke und eine Übereinstimmung mit einem davon ist akzeptabel, dann
ist es möglich, sie zu einer Reihe von Alternativen zu kombinieren. Wenn die einzelnen Ausdrücke
Eingabedaten kann dies durch die Programmierung einer Join-Operation erreicht werden. Wir werden diese Idee in
eine verbesserte Version des Programms "simple_grep": ein Programm, das mehrere
Muster:

% Katze > multi_grep
#!/ Usr / bin / perl
# multi_grep - entspricht einem der reguläre Ausdrücke
# Verwendung: multi_grep regulärer Ausdruck1 regulärer Ausdruck2 ... Datei1 Datei2 ...

$Nummer = Verschiebung;
$regexp[$_] = Verschiebung für jeden (0..$Zahl-1);
$Muster = Join '|', @regexp;

während ($Zeile = <>) {
drucke $line, wenn $line =~ /$pattern/;
}
^D

% multi_grep 2 Verschiebung für multi_grep
$Nummer = Verschiebung;
$regexp[$_] = Verschiebung für jeden (0..$Zahl-1);

Manchmal ist es vorteilhaft, ein Muster aus dem Varianten des Eingangssignals: das soll analysiert werden
und verwenden Sie die zulässigen Werte auf der linken Seite der Matching-Operationen. Als
Als Beispiel für diese etwas paradoxe Situation nehmen wir an, dass unsere Eingabe eine
Befehlsverb, das mit einem aus einer Reihe verfügbarer Befehlsverben übereinstimmen sollte, mit dem
Zusätzlicher Clou: Befehle können abgekürzt werden, solange die angegebene Zeichenfolge eindeutig ist.
Das folgende Programm demonstriert den grundlegenden Algorithmus.

% Katze > Schlüsselübereinstimmung
#!/ Usr / bin / perl
$kwds = 'Liste kopieren, vergleichen, drucken';
während( $cmd = <> ){
$cmd =~ s/^\s+|\s+$//g; # führende und nachfolgende Leerzeichen entfernen
wenn( ( @matches = $kwds =~ /\b$cmd\w*/g ) == 1 ){
drucke "Befehl: '@matches'\n";
} elsif( @matches == 0 ){
print "Kein solcher Befehl: '$cmd'\n";
} Else {
print "nicht eindeutig: '$cmd' (könnte eines von @matches sein)\n";
}
}
^D

% Schlüsselübereinstimmung
li
Befehl: „Liste“
co
nicht eindeutig: „co“ (könnte eines von Folgendem sein: Kopieren, Vergleichen)
Drucker
kein solcher Befehl: „Drucker“

Anstatt zu versuchen, die Eingabe mit den Schlüsselwörtern abzugleichen, gleichen wir den kombinierten Satz von
Schlüsselwörter gegen die Eingabe. Die Mustervergleichsoperation "$kwds =~ /\b($cmd\w*)/g"
mehrere Dinge gleichzeitig. Es stellt sicher, dass der gegebene Befehl dort beginnt, wo ein
Schlüsselwort beginnt mit "\b". Es toleriert Abkürzungen durch das hinzugefügte "\w*". Es sagt uns,
Anzahl der Übereinstimmungen („skalare @matches“) und alle Schlüsselwörter, die tatsächlich übereinstimmten.
Mehr kann man kaum verlangen.

Einbetten Bemerkungen und Modifikatoren in a regulär Ausdruck
Beginnend mit diesem Abschnitt werden wir Perls Satz von verlängert Muster. Diese
sind Erweiterungen der traditionellen regulären Ausdruckssyntax, die leistungsstarke neue
Werkzeuge für den Mustervergleich. Wir haben bereits Erweiterungen in Form der minimalen
passende Konstrukte "??", "*?", "+?", "{n,m}?" und "{n,}?". Die meisten der folgenden Erweiterungen
haben die Form "(?char...)", wobei das "char" ein Zeichen ist, das den Typ des
Erweiterung.

Die erste Erweiterung ist ein eingebetteter Kommentar "(?#text)". Dies bettet einen Kommentar in die
regulären Ausdruck, ohne seine Bedeutung zu beeinflussen. Der Kommentar sollte keine schließenden
Klammern im Text. Ein Beispiel ist

/(?# Entspricht einer Ganzzahl:)[+-]?\d+/;

Dieser Kommentarstil wurde weitgehend durch den rohen, freien Kommentar ersetzt, der
ist mit dem Modifikator „//x“ zulässig.

Die meisten Modifikatoren wie "//i", "//m", "//s" und "//x" (oder eine beliebige Kombination davon) können
kann auch in einen regulären Ausdruck mit "(?i)", "(?m)", "(?s)" und "(?x)" eingebettet werden. Zum Beispiel

/(?i)yes/; # Groß-/Kleinschreibung von „yes“ ignorieren
/ja/i; # dasselbe
/(?x)( # Freiformversion eines ganzzahligen regulären Ausdrucks
[+-]? # entspricht einem optionalen Zeichen
\d+ # eine Ziffernfolge abgleichen
)
/X;

Eingebettete Modifikatoren können gegenüber den üblichen Modifikatoren zwei wichtige Vorteile haben. Eingebettete
Modifikatoren ermöglichen einen benutzerdefinierten Satz von Modifikatoren jeder Regexp-Muster. Das ist ideal für
Übereinstimmung mit einem Array von regulären Ausdrücken, die unterschiedliche Modifikatoren haben müssen:

$pattern[0] = '(?i)Arzt';
$muster[1] = 'Johnson';
...
während (<>) {
foreach $patt (@pattern) {
drucken, wenn /$patt/;
}
}

Der zweite Vorteil ist, dass eingebettete Modifikatoren (außer "//p", der die gesamte
regexp) wirken sich nur auf den regulären Ausdruck innerhalb der Gruppe aus, in der der eingebettete Modifikator enthalten ist.
Durch Gruppieren können die Auswirkungen des Modifikators lokalisiert werden:

/Antwort: ((?i)ja)/; # entspricht „Antwort: ja“, „Antwort: JA“ usw.

Eingebettete Modifikatoren können auch bereits vorhandene Modifikatoren deaktivieren, indem sie beispielsweise Folgendes verwenden:
Modifikatoren können auch zu einem einzigen Ausdruck kombiniert werden, z. B. aktiviert "(?si)"
Einzelzeilenmodus und deaktiviert die Groß-/Kleinschreibung.

Eingebettete Modifikatoren können auch zu einer nicht erfassenden Gruppierung hinzugefügt werden. "(?im:regexp)" ist ein
nicht erfassende Gruppierung, die die Groß- und Kleinschreibung von „regexp“ unempfindlich berücksichtigt und mehrzeilige
Modus arbeiten können.

Auf der Suche voraus und suchen hinter
Dieser Abschnitt befasst sich mit den Lookahead- und Lookbehind-Assertionen. Zunächst ein wenig
Hintergrund.

In regulären Perl-Ausdrücken verbrauchen die meisten Regexp-Elemente eine bestimmte Menge an String, wenn
sie passen. Beispielsweise verbraucht das Regexp-Element "[abc}]" ein Zeichen der Zeichenfolge
wenn es übereinstimmt, in dem Sinne, dass Perl zur nächsten Zeichenposition in der Zeichenfolge wechselt
nach dem Spiel. Es gibt jedoch einige Elemente, die keine Charaktere fressen (Voraus
die Zeichenposition), wenn sie übereinstimmen. Die Beispiele, die wir bisher gesehen haben, sind die Anker.
Der Anker "^" passt zum Zeilenanfang, frisst aber keine Zeichen.
Ebenso passt der Wortgrenzenanker "\b" überall dort, wo ein Zeichen, das mit "\w" übereinstimmt,
neben einem Charakter, der dies nicht tut, aber es frisst selbst keine Charaktere. Anker
sind Beispiele für Nullbreite Behauptungen: Nullbreite, da sie keine Zeichen verbrauchen, und
Behauptungen, weil sie eine Eigenschaft der Zeichenfolge testen. Im Kontext unseres Spaziergangs in
Die Waldanalogie zum Regexp-Matching: Die meisten Regexp-Elemente bewegen uns entlang eines Pfades, aber
Anker lassen uns einen Moment innehalten und unsere Umgebung überprüfen. Wenn die lokale Umgebung überprüft
Wenn wir mit der lokalen Umgebung nicht zufrieden sind, müssen wir
zurückverfolgen.

Die Umgebung zu überprüfen bedeutet entweder, nach vorne auf den Weg zu schauen, nach hinten zu schauen oder
beides. "^" blickt nach hinten, um zu sehen, dass davor keine Zeichen stehen. "$" blickt nach vorne, um
sehen Sie, dass keine Zeichen danach kommen. "\b" schaut sowohl nach vorne als auch nach hinten, um zu sehen, ob die
Die Charaktere auf beiden Seiten unterscheiden sich in ihrer „Worthaftigkeit“.

Die Lookahead- und Lookbehind-Behauptungen sind Verallgemeinerungen des Ankerkonzepts.
Lookahead und Lookbehind sind Null-Breiten-Assertionen, mit denen wir angeben können, welche Zeichen wir
testen möchten. Die Lookahead-Assertion wird durch "(?=regexp)" gekennzeichnet und die Lookbehind-Assertion
Assertion wird durch "(?<=fixed-regexp)" gekennzeichnet. Einige Beispiele sind

$x = "Ich fange die Hauskatze 'Kater' mit Katzenminze";
$x =~ /cat(?=\s)/; # entspricht „cat“ in „housecat“
@catwords = ($x =~ /(?<=\s)cat\w+/g); # Übereinstimmungen,
# $catwords[0] = 'fangen'
# $catwords[1] = 'Katzenminze'
$x =~ /\bcat\b/; # entspricht „Katze“ in „Kater“
$x =~ /(?<=\s)cat(?=\s)/; # passt nicht; keine isolierte 'Katze' in
# Mitte von $x

Beachten Sie, dass die Klammern in "(?=regexp)" und "(?<=regexp)" nicht erfassend sind, da diese
sind Behauptungen mit Nullbreite. Daher sind im zweiten regulären Ausdruck die erfassten Teilzeichenfolgen diejenigen
des gesamten regulären Ausdrucks selbst. Lookahead "(?=regexp)" kann beliebige reguläre Ausdrücke abgleichen, aber
lookbehind "(?<=fixed-regexp)" funktioniert nur für reguläre Ausdrücke mit fester Breite, also einer festen Anzahl
Zeichen lang sein. Daher ist "(?<=(ab|bc))" in Ordnung, "(?<=(ab)*)" jedoch nicht. Die negierte
Versionen der Lookahead- und Lookbehind-Assertionen werden durch "(?!regexp)" gekennzeichnet und
"(? nicht Spiel:

$x = "foobar";
$x =~ /foo(?!bar)/; # stimmt nicht überein, „bar“ folgt auf „foo“
$x =~ /foo(?!baz)/; # Übereinstimmungen, „baz“ folgt nicht auf „foo“
$x =~ /(?

Das "\C" wird im Lookbehind nicht unterstützt, da die ohnehin schon tückische Definition von "\C"
Dies würde sich bei einer Rückwärtsbewegung noch verstärken.

Hier ist ein Beispiel, wo eine Zeichenfolge mit durch Leerzeichen getrennten Wörtern, Zahlen und einzelnen
Bindestriche sollen in ihre Bestandteile zerlegt werden. Die Verwendung von "/\s+/" allein funktioniert nicht, da Leerzeichen
sind zwischen Bindestrichen oder einem Wort oder einem Bindestrich nicht erforderlich. Zusätzliche Stellen für eine Trennung sind
durch den Blick nach vorn und zurück festgelegt:

$str = "eins zwei - --6-8";
@toks = split / \s+ # eine Reihe von Leerzeichen
| (?<=\S) (?=-) # alle Nicht-Leerzeichen, gefolgt von '-'
| (?<=-) (?=\S) # ein '-' gefolgt von einem beliebigen Zeichen, das kein Leerzeichen ist
/x, $str; # @toks = qw(eins zwei - - - 6 - 8)

Die richtigen unabhängig Unterausdrücke zu verhindern Rückzieher
Unabhängig Unterausdrücke sind reguläre Ausdrücke, im Kontext einer größeren regulären
Ausdruck, die unabhängig vom größeren regulären Ausdruck funktionieren. Das heißt, sie
verbrauchen so viel oder so wenig von der Saite, wie sie wollen, ohne Rücksicht auf die Fähigkeit von
der größere reguläre Ausdruck, der übereinstimmen soll. Unabhängige Teilausdrücke werden durch "(?>regexp)" dargestellt.
Wir können ihr Verhalten veranschaulichen, indem wir zunächst einen gewöhnlichen regulären Ausdruck betrachten:

$x = "ab";
$x =~ /a*ab/; # Übereinstimmungen

Dies passt offensichtlich, aber im Prozess der Übereinstimmung wird der Teilausdruck "a*" zuerst
das "a" gepackt. Dies würde jedoch nicht dazu führen, dass der gesamte reguläre Ausdruck übereinstimmt.
Beim Zurückverfolgen gab "a*" schließlich das "a" zurück und passte zur leeren Zeichenfolge. Hier, was
"a*" wurde gefunden abhängig davon ab, was mit dem Rest des regulären Ausdrucks übereinstimmte.

Vergleichen Sie das mit einem unabhängigen Unterausdruck:

$x =~ /(?>a*)ab/; # stimmt nicht überein!

Der unabhängige Teilausdruck "(?>a*)" kümmert sich nicht um den Rest des regulären Ausdrucks, also
sieht ein "a" und greift es. Dann kann der Rest des regulären Ausdrucks "ab" nicht übereinstimmen. Weil
"(?>a*)" ist unabhängig, es gibt kein Backtracking und der unabhängige Teilausdruck
gibt sein "a" nicht auf. Daher schlägt die Übereinstimmung des regulären Ausdrucks als Ganzes fehl. Ein ähnliches Verhalten
tritt bei völlig unabhängigen regulären Ausdrücken auf:

$x = "ab";
$x =~ /a*/g; # passt, isst ein 'a'
$x =~ /\Gab/g; # passt nicht, kein 'a' verfügbar

Hier erstellen "//g" und "\G" eine 'Tag-Team'-Übergabe der Zeichenfolge von einem regulären Ausdruck zum
andere. Reguläre Ausdrücke mit einem unabhängigen Teilausdruck sind ähnlich, mit einer Übergabe von
die Zeichenfolge an den unabhängigen Teilausdruck und eine Übergabe der Zeichenfolge zurück an den
umschließender regulärer Ausdruck.

Die Fähigkeit eines unabhängigen Unterausdrucks, Backtracking zu verhindern, kann sehr nützlich sein.
Angenommen, wir möchten eine nicht leere Zeichenfolge abgleichen, die in Klammern eingeschlossen ist und bis zu zwei Ebenen tief ist.
Dann stimmt der folgende reguläre Ausdruck überein:

$x = "abc(de(fg)h"; # ungleichmäßige Klammern
$x =~ /\( ( [^()]+ | \([^()]*\) )+ \)/x;

Der reguläre Ausdruck entspricht einer öffnenden Klammer, einer oder mehreren Kopien einer Alternation und einer schließenden
Klammern. Die Abwechslung ist zweiseitig, wobei die erste Alternative "[^()]+" einem
Teilzeichenfolge ohne Klammern und die zweite Alternative "\([^()]*\)" passend zu einem
Teilzeichenfolge durch Klammern getrennt. Das Problem mit diesem regulären Ausdruck ist, dass er
pathologisch: Es hat verschachtelte unbestimmte Quantifikatoren der Form "(a+|b)+". Wir diskutierten
in Teil 1, wie verschachtelte Quantifizierer wie diese exponentiell lange brauchen könnten, um
ausführen, wenn keine Übereinstimmung möglich ist. Um die exponentielle Explosion zu verhindern, müssen wir
nutzloses Backtracking zu verhindern. Dies kann durch das Einschließen der inneren
Quantifizierer als unabhängiger Teilausdruck:

$x =~ /\( ( (?>[^()]+) | \([^()]*\) )+ \)/x;

Hier durchbricht "(?>[^()]+)" die Entartung der String-Partitionierung, indem es so viel wie möglich verschlingt
die Zeichenfolge so schnell wie möglich und behalten. Dann schlagen Übereinstimmungsfehler viel schneller fehl.

Bedingt Ausdrücke
A bedingt Ausdruck ist eine Form der if-then-else-Anweisung, die es ermöglicht, zu wählen
welche Muster auf Grundlage einer bestimmten Bedingung abgeglichen werden sollen. Es gibt zwei Arten von
bedingter Ausdruck: "(?(condition)yes-regexp)" und
"(?(Bedingung)Ja-regulärer Ausdruck|Kein-regulärer Ausdruck)". "(?(Bedingung)Ja-regulärer Ausdruck)" ist wie ein 'if () {}'
Anweisung in Perl. Wenn die Bedingung erfüllt ist, wird der "Ja-Regexp" abgeglichen. Wenn die
"condition" ist falsch, der "yes-regexp" wird übersprungen und Perl geht zum nächsten
regexp-Element. Die zweite Form entspricht einer 'if () {} else {}'-Anweisung in Perl. Wenn das
"Bedingung" ist wahr, der "Ja-Regex" wird abgeglichen, andernfalls wird der "Nein-Regex"
abgestimmt.

Die "Bedingung" kann mehrere Formen haben. Die erste Form ist einfach eine Ganzzahl in
Klammern "(integer)". Es ist wahr, wenn die entsprechende Rückreferenz "\integer" übereinstimmte
früher im regulären Ausdruck. Dasselbe kann mit einem Namen gemacht werden, der mit einem Capture verknüpft ist
Gruppe, geschrieben als "( )" oder "('name')". Die zweite Form ist eine reine Nullbreite
Assertion "(?...)", entweder ein Lookahead, ein Lookbehind oder eine Code-Assertion (besprochen in
im nächsten Abschnitt). Der dritte Satz von Formularen bietet Tests, die true zurückgeben, wenn die
Der Ausdruck wird innerhalb einer Rekursion ("(R)") ausgeführt oder von einer Erfassungsfunktion aufgerufen.
Gruppe, referenziert entweder durch Nummer ("(R1)", "(R2)",...) oder durch Namen ("(R&Name)").

Die Ganzzahl- oder Namensform der "Bedingung" ermöglicht uns eine flexiblere Auswahl,
was zu entsprechen, basierend auf dem, was zuvor im regulären Ausdruck übereinstimmte. Dies sucht nach Wörtern der
Form "$x$x" oder "$x$y$y$x":

% simple_grep '^(\w+)(\w+)?(?(2)\g2\g1|\g1)$' /usr/dict/words
Beriberi
Kokos
Couscous
Urkunde
...
blasen
toto
Tutu

Die Lookbehind-"Bedingung" ermöglicht, zusammen mit Rückverweisen, einen früheren Teil der Übereinstimmung
um einen späteren Teil des Spiels zu beeinflussen. Zum Beispiel

/[ATGC]+(?(?<=AA)G|C)$/;

stimmt mit einer DNA-Sequenz überein, die entweder mit „AAG“ oder einem anderen Basenpaar endet
Kombination und "C". Beachten Sie, dass die Form "(?(?<=AA)G|C)" und nicht "(?((?<=AA))G|C)" ist; für
Bei den Lookahead-, Lookbehind- oder Code-Assertions sind die Klammern um die Bedingung
nicht benötigt.

Definieren namens Muster
Einige reguläre Ausdrücke verwenden identische Teilmuster an mehreren Stellen. Beginnend mit Perl
5.10 ist es möglich, benannte Untermuster in einem Abschnitt des Musters zu definieren, so dass sie
kann überall im Muster mit Namen aufgerufen werden. Dieses syntaktische Muster für dieses
Definitionsgruppe ist "(?(DEFINE)(? Muster)...)". Das Einfügen eines benannten Musters ist
geschrieben als "(?&name)".

Das folgende Beispiel veranschaulicht diese Funktion anhand des Musters für Gleitkommazahlen
das zuvor vorgestellt wurde. Die drei Untermuster, die mehr als einmal verwendet werden, sind die
optionales Vorzeichen, die Ziffernfolge für eine Ganzzahl und den Dezimalbruch. Das DEFINE
Gruppe am Ende des Musters enthält ihre Definition. Beachten Sie, dass die Dezimal
Das Bruchmuster ist der erste Ort, an dem wir das Ganzzahlmuster wiederverwenden können.

/^ (?&osg)\ * ( (?&int)(?&dec)? | (?&dec) )
(?: [eE](?&osg)(?&int) )?
$
(?(DEFINIEREN)
(? [-+]?) # optionales Zeichen
(? \d++) # Ganzzahl
(? \.(?&int)) # Dezimalbruch
)/X

Rekursive Muster
Diese Funktion (eingeführt in Perl 5.10) erweitert die Leistungsfähigkeit des Perl-Musters erheblich
Übereinstimmung. Durch Verweisen auf eine andere Erfassungsgruppe irgendwo im Muster mit dem
Konstrukt "(?group-ref)", die Anleitungen innerhalb der referenzierten Gruppe dient als
unabhängiges Untermuster anstelle der Gruppenreferenz selbst. Da die Gruppe
Referenz kann enthalten sein . der Gruppe, auf die es sich bezieht, ist es nun möglich,
Mustervergleich für Aufgaben, die bisher einen rekursiven Parser erforderten.

Um diese Funktion zu veranschaulichen, entwerfen wir ein Muster, das zutrifft, wenn eine Zeichenfolge Folgendes enthält:
Palindrom. (Dies ist ein Wort oder ein Satz, der unter Berücksichtigung von Leerzeichen, Interpunktion
und Fall, liest sich rückwärts wie vorwärts gleich. Wir beginnen mit der Beobachtung, dass die leere
Zeichenfolge oder eine Zeichenfolge, die nur ein Wortzeichen enthält, ist ein Palindrom. Andernfalls muss
haben ein Wortzeichen am Anfang und dasselbe am Ende, mit einem weiteren Palindrom in
zwischen.

/(?: (\w) (?...Hier ist ein Palindrom...) \g{-1} | \w? )/x

Wenn wir an beiden Enden "\W*" hinzufügen, um das zu ignorierende Element auszuschließen, haben wir bereits die vollständige
Muster:

mein $pp = qr/^(\W* (?: (\w) (?1) \g{-1} | \w? ) \W*)$/ix;
für $s („saippuakauppias“, „Ein Mann, ein Plan, ein Kanal: Panama!“){
print "'$s' ist ein Palindrom\n" if $s =~ /$pp/;
}

In "(?...)" können sowohl absolute als auch relative Rückverweise verwendet werden. Das gesamte Muster kann
mit "(?R)" oder "(?0)" wieder eingefügt werden. Wenn Sie Ihre Gruppen lieber benennen möchten, können Sie
"(?&name)", um in diese Gruppe zu rekursieren.

A Bit of Magie: Ausführung Perl Code in a regulär Ausdruck
Normalerweise sind reguläre Ausdrücke Teil von Perl-Ausdrücken. Code Auswertung Ausdrücke drehen das
umzugehen, indem beliebiger Perl-Code Teil eines regulären Ausdrucks sein kann. Eine Code-Auswertung
Ausdruck wird mit "(?{code})" gekennzeichnet, mit Code eine Folge von Perl-Anweisungen.

Beachten Sie, dass diese Funktion als experimentell gilt und ohne Vorankündigung geändert werden kann.

Codeausdrücke sind Aussagen mit Nullbreite, und der von ihnen zurückgegebene Wert hängt von ihrer
Umgebung. Es gibt zwei Möglichkeiten: Entweder wird der Codeausdruck als
bedingt in einem bedingten Ausdruck "(?(Bedingung)...)", oder es ist nicht. Wenn der Code
Ausdruck ist eine Bedingung, der Code wird ausgewertet und das Ergebnis (dh das Ergebnis der
letzte Aussage) wird verwendet, um Wahrheit oder Falschheit zu bestimmen. Wenn der Codeausdruck nicht
Wird die Aussage als Bedingung verwendet, wird sie immer als wahr ausgewertet und das Ergebnis wird in die
spezielle Variable $^R. Die Variable $^R kann dann später in Codeausdrücken im
regulärer Ausdruck. Hier sind einige alberne Beispiele:

$x = "abcdef";
$x =~ /abc(?{print "Hi Mom!";})def/; # Übereinstimmungen,
# druckt „Hallo Mama!“
$x =~ /aaa(?{print "Hi Mom!";})def/; # stimmt nicht überein,
# kein „Hallo Mama!“

Achten Sie genau auf das nächste Beispiel:

$x =~ /abc(?{print "Hi Mom!";})ddd/; # stimmt nicht überein,
# kein „Hallo Mama!“
# aber warum nicht?

Auf den ersten Blick könnte man meinen, dass es nicht gedruckt werden sollte, da das "ddd" offensichtlich nicht
wird mit der Zielzeichenfolge übereinstimmen. Aber sehen Sie sich dieses Beispiel an:

$x =~ /abc(?{print "Hi Mom!";})[dD]dd/; # stimmt nicht überein,
# aber _druckt_

Hmm. Was ist hier passiert? Wenn Sie mitgelesen haben, wissen Sie, dass das obige Muster
sollte praktisch (fast) dasselbe sein wie das letzte; das "d" in einem Zeichen einschließend
Klasse wird nicht ändern, was sie entspricht. Warum wird also die erste nicht gedruckt, während die
der zweite schon?

Die Antwort liegt in den Optimierungen, die die Regex-Engine vornimmt. Im ersten Fall werden alle
Engine sieht, sind einfache alte Zeichen (abgesehen von der "?{}"-Konstruktion). Es ist intelligent genug
um zu erkennen, dass die Zeichenfolge 'ddd' in unserer Zielzeichenfolge nicht vorkommt, bevor tatsächlich
das Muster durchlaufen. Aber im zweiten Fall haben wir es dazu gebracht zu denken, dass
unser Muster ist komplizierter. Es wirft einen Blick auf unsere Charakterklasse und entscheidet
dass das Muster tatsächlich ausgeführt werden muss, um festzustellen, ob es übereinstimmt oder nicht, und
während der Ausführung stößt es auf die Druckanweisung, bevor es feststellt, dass wir nicht
ein Match haben.

Um einen genaueren Blick auf die Optimierungen der Engine zu werfen, siehe den Abschnitt „Pragmas und
Debuggen" weiter unten.

Mehr Spaß mit "?{}":

$x =~ /(?{print "Hi Mom!";})/; # Übereinstimmungen,
# druckt „Hallo Mama!“
$x =~ /(?{$c = 1;})(?{print "$c";})/; # Übereinstimmungen,
# gibt „1“ aus
$x =~ /(?{$c = 1;})(?{print "$^R";})/; # Übereinstimmungen,
# gibt „1“ aus

Der im Abschnittstitel erwähnte kleine Zauber tritt ein, wenn der reguläre Ausdruck in der
Prozess der Suche nach einer Übereinstimmung. Wenn der reguläre Ausdruck über einen Codeausdruck zurückverfolgt und wenn
Die darin verwendeten Variablen werden mit "local" lokalisiert, die Änderungen in den Variablen
Die durch den Code-Ausdruck erzeugten Aktionen werden rückgängig gemacht! Wenn wir also zählen wollten, wie oft ein
Zeichen wurde innerhalb einer Gruppe gefunden, wir könnten beispielsweise verwenden,

$x = "aaaa";
$count = 0; # initialisiere 'a' count
$c = "bob"; # Test, ob $c beschädigt wird
$x =~ /(?{local $c = 0;}) # Anzahl initialisieren
( eine # Übereinstimmung mit 'a'
(?{local $c = $c + 1;}) # Anzahl erhöhen
)* # wiederholen Sie dies beliebig oft,
aa #, aber am Ende mit 'aa' übereinstimmen
(?{$count = $c;}) # kopiere lokale $c-Variable in $count
/X;
print "'a'-Anzahl ist $count, \$c-Variable ist '$c'\n";

Dies wird gedruckt

'a'-Anzahl ist 2, $c-Variable ist 'bob'

Wenn wir " (?{local $c = $c + 1;})" durch " (?{$c = $c + 1;})" ersetzen, wird die Variable
Änderungen sind nicht beim Backtracking rückgängig gemacht, und wir erhalten

'a'-Anzahl ist 4, $c-Variable ist 'bob'

Beachten Sie, dass nur lokalisierte Variablenänderungen rückgängig gemacht werden. Andere Nebeneffekte des Codes
Ausdrucksausführung sind permanent. Somit

$x = "aaaa";
$x =~ /(a(?{print "Yow\n";}))*aa/;

produziert

Yow
Yow
Yow
Yow

Das Ergebnis $^R wird automatisch lokalisiert, so dass es sich in Gegenwart von
des Zurückverfolgens.

Dieses Beispiel verwendet einen Codeausdruck in einer Bedingung, um einen bestimmten Artikel abzugleichen, entweder
'the' auf Englisch oder 'der|die|das' auf Deutsch:

$lang = 'DE'; # benutze Deutsch
...
$text = "das";
drucke "übereinstimmend\n"
wenn $text =~ /(?(?{
$lang eq 'EN'; # ist die Sprache Englisch?
})
das | # wenn ja, dann vergleiche 'das'
(der|die|das) # else, match 'der|die|das'
)
/xi;

Beachten Sie, dass die Syntax hier "(?(?{...})yes-regexp|no-regexp)" ist, nicht
"(?((?{...}))yes-regexp|no-regexp)". Anders ausgedrückt: Im Falle eines Code-Ausdrucks
brauchen die zusätzlichen Klammern um die Bedingung nicht.

Wenn Sie versuchen, Codeausdrücke zu verwenden, bei denen der Codetext in einem interpolierten
Variable, anstatt wörtlich im Muster zu erscheinen, könnte Perl Sie überraschen:

$bar = 5;
$pat = '(?{ 1 })';
/foo(?{ $bar })bar/; # kompiliert ordnungsgemäß, $bar nicht interpoliert
/foo(?{ 1 })$bar/; # kompiliert ok, $bar interpoliert
/foo${pat}bar/; # Kompilierungsfehler!

$pat = qr/(?{ $foo = 1 })/; # Code-Regexp vorkompilieren
/foo${pat}bar/; # wird ordnungsgemäß kompiliert

Wenn ein regulärer Ausdruck eine Variable hat, die einen Codeausdruck interpoliert, behandelt Perl den regulären Ausdruck als
ein Fehler. Wenn der Code-Ausdruck jedoch in eine Variable vorkompiliert ist, ist die Interpolation
ok. Die Frage ist, warum ist das ein Fehler?

Der Grund dafür ist, dass variable Interpolation und Codeausdrücke zusammen eine Sicherheitslücke darstellen.
Risiko. Die Kombination ist gefährlich, weil viele Programmierer, die Suchmaschinen schreiben
Nehmen Sie häufig Benutzereingaben entgegen und fügen Sie diese direkt in einen regulären Ausdruck ein:

$regexp = <>; # vom Benutzer bereitgestellten regulären Ausdruck lesen
$chomp $regexp; # mögliche Zeilenumbrüche entfernen
$text =~ /$regexp/; # durchsuche $text nach dem $regexp

Wenn die Variable $regexp einen Codeausdruck enthält, könnte der Benutzer beliebige
Perl-Code. Ein Witzbold könnte zum Beispiel nach "system('rm -rf *');" suchen, um Ihre
Dateien. In diesem Sinne ist die Kombination von Interpolation und Codeausdrücken flecken Wir koordinieren den Versand
regulärer Ausdruck. Standardmäßig werden Interpolations- und Codeausdrücke im selben regulären Ausdruck verwendet.
ist nicht erlaubt. Wenn Sie sich keine Sorgen über böswillige Benutzer machen, können Sie
diese Sicherheitsüberprüfung durch Aufruf von „use re 'eval'“:

benutze re 'eval'; # wirf die Vorsicht über Bord
$bar = 5;
$pat = '(?{ 1 })';
/foo${pat}bar/; # wird ordnungsgemäß kompiliert

Eine weitere Form des Code-Ausdrucks ist die Anleitungen Code AusdruckDer Mustercode
Ausdruck ist wie ein regulärer Codeausdruck, außer dass das Ergebnis des Codes
Die Auswertung wird als regulärer Ausdruck behandelt und sofort abgeglichen. Ein einfaches Beispiel
is

$Länge = 5;
$char = 'a';
$x = 'aaaaabb';
$x =~ /(??{$char x $length})/x; # Übereinstimmungen, es gibt 5 von 'a'

Dieses letzte Beispiel enthält sowohl normale als auch Mustercode-Ausdrücke. Es erkennt
ob eine Binärzeichenfolge 1101010010001... einen Fibonacci-Abstand 0,1,1,2,3,5,... der
1er:

$x = "1101010010001000001";
$z0 = ''; $z1 = '0'; # Anfangsbedingungen
print "Es ist eine Fibonacci-Folge\n"
if $x =~ /^1 # entspricht einer anfänglichen „1“
(?:
((??{ $z0 })) # entspricht einer '0'
1 # und dann eine '1'
(?{ $z0 = $z1; $z1 .= $^N; })
)+ # bei Bedarf wiederholen
$ # das ist alles, was es gibt
/X;
printf "Die größte übereinstimmende Sequenz war %d\n", Länge($z1)-Länge($z0);

Beachten Sie, dass $^N auf den Wert gesetzt wird, der mit der letzten abgeschlossenen Erfassungsgruppe übereinstimmt. Dies
Drucke

Es handelt sich um eine Fibonacci-Folge
Die größte übereinstimmende Sequenz war 5

Ha! Versuchen Sie das mal mit Ihrem gewöhnlichen Regexp-Paket ...

Beachten Sie, dass die Variablen $z0 und $z1 beim Kompilieren des regulären Ausdrucks nicht ersetzt werden, da
geschieht für gewöhnliche Variablen außerhalb eines Code-Ausdrucks. Vielmehr wird der gesamte Code-Block
als Perl-Code analysiert, während Perl den Code kompiliert, der das Literal enthält
Regexp-Muster.

Der reguläre Ausdruck ohne den Modifikator "//x" ist

/^1(?:((??{ $z0 }))1(?{ $z0 = $z1; $z1 .= $^N; }))+$/

Dies zeigt, dass Leerzeichen in den Codeteilen immer noch möglich sind. Trotzdem beim Arbeiten
mit Code und bedingten Ausdrücken ist die erweiterte Form von Regexps fast notwendig in
Erstellen und Debuggen von regulären Ausdrücken.

Backtracking Smartgeräte App Verben
Perl 5.10 führte eine Reihe von Steuerverben ein, die eine detaillierte Kontrolle über
den Backtracking-Prozess, indem er direkt auf die Regexp-Engine einwirkt und
Überwachungstechniken. Da alle Funktionen in dieser Gruppe experimentell sind und
Änderungen oder Entfernungen in einer zukünftigen Version von Perl werden dem interessierten Leser
Eine ausführliche Beschreibung finden Sie unter „Spezielle Backtracking-Steuerverben“ in perlre.

Nachfolgend sehen Sie nur ein Beispiel, das das Kontrollverb "(*FAIL)" veranschaulicht, das
abgekürzt als "(*F)". Wenn dies in einen regulären Ausdruck eingefügt wird, führt es dazu, dass dieser fehlschlägt, genau wie
Es würde zu einer Nichtübereinstimmung zwischen dem Muster und der Zeichenfolge kommen. Die Verarbeitung des regulären Ausdrucks
läuft weiter wie nach jedem "normalen" Ausfall, so dass zum Beispiel die nächste Position
in der Zeichenfolge oder eine andere Alternative wird versucht. Da keine Übereinstimmung besteht, bleibt
Gruppen erfassen oder Ergebnisse erzielen, kann es notwendig sein, dies in Kombination mit
eingebetteter Code.

%Anzahl = ();
"supercalifragilisticexpialidocious" =~
/([aeiou])(?{ $count{$1}++; })(*FAIL)/i;
printf "%3d '%s'\n", $count{$_}, $_ für (Sortierschlüssel %count);

Das Muster beginnt mit einer Klasse, die einer Teilmenge von Buchstaben entspricht. Immer wenn diese übereinstimmt,
Anweisung wie "$count{'a'}++;" wird ausgeführt und erhöht den Zähler des Buchstabens. Dann
"(*FAIL)" tut, was es sagt, und die Regexp-Engine verfährt nach Vorschrift: solange
Da das Ende der Zeichenfolge noch nicht erreicht ist, wird die Position vorgerückt, bevor nach
ein weiterer Vokal. Daher macht es keinen Unterschied, ob eine Übereinstimmung vorliegt oder nicht, und die Regexp-Engine fährt fort
bis die gesamte Saite geprüft wurde. (Es ist bemerkenswert, dass eine alternative Lösung
mit etwas wie

$count{lc($_)}++ für split('', "supercalifragilisticexpialidocious");
printf "%3d '%s'\n", $count2{$_}, $_ for ( qw{ aeiou } );

ist erheblich langsamer.)

Pragmen und Debugging
Apropos Debuggen: Es gibt mehrere Pragmas zur Steuerung und zum Debuggen von regulären Ausdrücken in
Perl. Wir sind im vorherigen Abschnitt bereits auf ein Pragma gestoßen: "use re 'eval';",
Dies ermöglicht die Koexistenz von Variableninterpolation und Codeausdrücken in einem regulären Ausdruck. Die andere
Pragmas sind

verwenden Sie „Makel“;
$tainted = <>;
@parts = ($tainted =~ /(\w+)\s+(\w+)/; # @parts ist jetzt verdorben

Das Pragma "taint" bewirkt, dass alle Teilzeichenfolgen aus einer Übereinstimmung mit einer verdorbenen Variable
verdorben. Dies ist normalerweise nicht der Fall, da Regexps oft verwendet werden, um die
sichere Bits aus einer verdorbenen Variable. Verwenden Sie "taint", wenn Sie keine sicheren Bits extrahieren, sondern
führen eine andere Verarbeitung durch. Sowohl "taint" als auch "eval" Pragmas sind lexikalisch
scoped, das heißt, sie sind nur bis zum Ende des Blocks gültig, der die
Pragmen.

benutze re '/m'; # oder andere Flags
$multiline_string =~ /^foo/; # /m ist impliziert

Das Pragma "re '/flags'" (eingeführt in Perl 5.14) aktiviert den angegebenen regulären Ausdruck
Flags bis zum Ende des lexikalischen Gültigkeitsbereichs. Weitere Informationen finden Sie unter „Modus '/flags'“ in re.

benutze re 'debug';
/^(.*)$/s; # Debuginformationen ausgeben

verwenden Sie erneut „Debugcolor“;
/^(.*)$/s; # gibt Debuginformationen in lebendigen Farben aus

Die globalen Pragmas "debug" und "debugcolor" ermöglichen es, detaillierte Debuginformationen zu erhalten über
Kompilierung und Ausführung von regulären Ausdrücken. „debugcolor“ ist dasselbe wie „debug“, außer dass das Debuggen
Auf Terminals, die Termcap-Farbsequenzen anzeigen können, werden Informationen farbig angezeigt.
Hier ist eine Beispielausgabe:

% perl -e 'verwenden Sie re "debug"; "abc" =~ /a*b+c/;'
Kompilieren von REx 'a*b+c'
Größe 9 zuerst bei 1
1: STAR(4)
2: GENAU (0)
4: PLUS(7)
5: GENAU (0)
7: GENAU (9)
9: ENDE(0)
Floating 'bc' bei 0..2147483647 (Überprüfung von Floating) Minlen 2
Raten Sie den Beginn des Spiels, REx „a*b+c“ gegen „abc“ …
Floating-Substr „bc“ bei Offset 1 gefunden …
Vermutet: Übereinstimmung bei Offset 0
REx 'a*b+c' mit 'abc' abgleichen
Festlegen eines EVAL-Bereichs, savestack=3
0 <> | 1: STERN
EXACT kann 1 von 32767 Mal übereinstimmen ...
Festlegen eines EVAL-Bereichs, savestack=3
1 | 4: PLUS
EXACT kann 1 von 32767 Mal übereinstimmen ...
Festlegen eines EVAL-Bereichs, savestack=3
2 | 7: GENAU
3 <> | 9: ENDE
Spiel erfolgreich!
REx freigeben: 'a*b+c'

Wenn Sie bis hierhin im Tutorial gekommen sind, können Sie wahrscheinlich erraten, was die verschiedenen
Teile der Debug-Ausgabe geben Auskunft. Der erste Teil

Kompilieren von REx 'a*b+c'
Größe 9 zuerst bei 1
1: STAR(4)
2: GENAU (0)
4: PLUS(7)
5: GENAU (0)
7: GENAU (9)
9: ENDE(0)

beschreibt die Kompilierungsphase. STAR(4) bedeutet, dass es sich um ein mit einem Stern markiertes Objekt handelt, in diesem
Fall 'a', und wenn es übereinstimmt, gehe zu Zeile 4, d. h. PLUS(7). Die mittleren Linien beschreiben einige
Heuristiken und Optimierungen, die vor einem Spiel durchgeführt werden:

Floating 'bc' bei 0..2147483647 (Überprüfung von Floating) Minlen 2
Raten Sie den Beginn des Spiels, REx „a*b+c“ gegen „abc“ …
Floating-Substr „bc“ bei Offset 1 gefunden …
Vermutet: Übereinstimmung bei Offset 0

Anschließend wird der Abgleich ausgeführt und die restlichen Zeilen beschreiben den Ablauf:

REx 'a*b+c' mit 'abc' abgleichen
Festlegen eines EVAL-Bereichs, savestack=3
0 <> | 1: STERN
EXACT kann 1 von 32767 Mal übereinstimmen ...
Festlegen eines EVAL-Bereichs, savestack=3
1 | 4: PLUS
EXACT kann 1 von 32767 Mal übereinstimmen ...
Festlegen eines EVAL-Bereichs, savestack=3
2 | 7: GENAU
3 <> | 9: ENDE
Spiel erfolgreich!
REx freigeben: 'a*b+c'

Jeder Schritt hat die Form "n ", mit " " der Teil der Zeichenfolge, der übereinstimmt und " "
der Teil, der noch nicht übereinstimmt. Das "| 1: STAR" bedeutet, dass Perl sich in Zeile 1 im
Kompilierungsliste oben. Weitere Informationen finden Sie unter "Debuggen regulärer Ausdrücke" in perldebguts
Detail.

Eine alternative Methode zum Debuggen von regulären Ausdrücken besteht darin, "print"-Anweisungen in die
regulärer Ausdruck. Dies bietet eine detaillierte Beschreibung des Backtrackings in einer Abwechslung:

"dass dies" =~ m@(?{print "Start bei Position ", pos, "\n";})
t(?{print "t1\n";})
h(?{print "h1\n";})
i(?{print "i1\n";})
s(?{print "s1\n";})
|
t(?{print "t2\n";})
h(?{print "h2\n";})
a(?{print "a2\n";})
t(?{print "t2\n";})
(?{print "Erledigt an Position ", pos, "\n";})
@X;

Drucke

Beginnen Sie bei Position 0
t1
h1
t2
h2
a2
t2
Fertig an Position 4

Verwenden Sie perlretut online mit den Diensten von onworks.net


Kostenlose Server & Workstations

Laden Sie Windows- und Linux-Apps herunter

Linux-Befehle

Ad




×
Werbung
❤ ️Hier einkaufen, buchen oder kaufen – kostenlos, damit die Dienste kostenlos bleiben.