Verrückte Dinge mit den Regex-Erweiterungen in Perl

(Auszug aus "Reguläre Ausdrücke" von Jeffrey E. F. Friedl)

Viele Dinge bei regulären Ausdrücken, die jetzt in vielen Sprachen vorhanden sind, wurden zuerst in Perl entwickelt. Dazu gehören beispielsweise die nicht-einfangenden Klammern, Lookahead (und später Lookbehind), der Modus »Freie Form« (eigentlich die meisten Modi und damit auch ˹\A˼, ˹\z˼ und ˹\Z˼), atomare Gruppen, ˹\G˼ und die bedingten (?if then|else)-Konstrukte. Diese sind nicht mehr nur Perl-spezifisch und wurden deshalb in den allgemeinen Kapiteln dieses Buches behandelt.

Die Perl-Entwickler sind aber nach wie vor innovativ und experimentierfreudig, es gibt daher einige wichtige neue Erweiterungen, die nur in Perl implementiert sind. Eine der interessantesten ist die Möglichkeit, in eine Regex Perl-Code einzubringen, der während eines Match-Versuchs ausgeführt wird. In Perl sind die regulären Ausdrücke sehr eng in die Programmiersprache eingebaut, aber damit wird eine neue Stufe erreicht. Ich stelle diese und andere Perl-spezifische Erweiterungen zunächst kurz vor, später in allen Einzelheiten.

Das dynamische Regex-Konstrukt ˹(??{Perl-Code})˼

Jedes Mal, wenn bei der Anwendung der Regex dieses Konstrukt erreicht wird, wird der darin enthaltene Perl-Code ausgeführt. Das Resultat (entweder ein Regex-Objekt oder ein String, der als Regex interpretiert wird) wird dann an dieser Stelle in die Regex in die laufende Mustersuche eingebaut.

Im einfachen Beispiel ˹^(\d+)(??{"X{$1}"}) ist das dynamische Regex-Konstrukt unterstrichen. Die Regex als Ganzes passt auf eine Zahl am Zeilenanfang, auf die exakt so viele ›X‹ folgen, wie die Zahl angibt. Sie passt auf ›3XXX‹ oder auf ›12XXXXXXXXXXXX‹, aber nicht auf ›3X‹ oder ›7XXXX‹.

Wir verfolgen das ›3XXX‹-Beispiel genauer: Zuerst passt der führende Teil ˹(\d+)˼ auf 3XXX‹, die Variable $1 bekommt den Wert ›3‹. Die Maschine erreicht nun das dynamische Konstrukt, führt den Perl-Code "X{$1}" aus und erhält als Resultat ›X{3}‹. Dies wird als ˹X{3}˼ interpretiert und als Teil der aktuellen Regex angewandt (und erkennt ›3XXX). Nach dem dynamischen Konstrukt passt ˹$˼ an der Stelle ›3XXX▵‹, und es wird ein Treffer für die ganze Regex gefunden.

In den späteren Beispielen werden Sie sehen, dass das dynamische Regex-Konstrukt insbesondere für das Erkennen von beliebig tief verschachtelten Elementen sehr nützlich ist.

Das Perl-Codemuster-Konstrukt ˹(?{Perl-Code})˼

Wie beim dynamischen Regex-Konstrukt wird auch bei diesem Konstrukt Perl-Code ausgeführt, sobald die Regex-Maschine die Klammer erreicht. Dieser Fall ist etwas allgemeiner: Hier muss der Code keine besondere Art von Rückgabewert liefern. Meist wird der Rückgabewert sogar einfach ignoriert (wenn nicht, ist er in der Variablen $^R verfügbar, siehe $^R).

In einem Fall wird der Rückgabewert direkt verwendet: wenn das Perl-Muster im if-Teil eines ˹(? if then|else-Konstrukts auftritt (siehe Bedingte reguläre Ausdrücke). Das Resultat wird als boolescher Wert interpretiert und je nachdem der then- oder der else-Teil angewendet.

Codemuster können für viele Zwecke verwendet werden. Sie sind besonders auch für das Debugging interessant. Im folgenden Beispiel wird immer dann eine Meldung ausgegeben, wenn die Regex vom Getriebe an einer neuen Position angesetzt wird. Das Codemuster-Konstrukt ist in Zeile 2:

"Nur ein kleines Beispiel" =~ m{
     (?{ print "Suche beginnt.\n" })
     \b(?: der | die | das | eine | ein )\b
}x;

Die Regex passt nur einmal, die Meldung wird aber fünfmal ausgegeben. Also wurde die Regex vom Getriebe an vier Positionen vergeblich angesetzt, bevor sie an der fünften Position passte.

Overloading: Überladen von Regex-Literalen

Mit dem Overloading kann man Regex-Literale nach eigenen Ideen vorverarbeiten, bevor sie an die Regex-Maschine weitergereicht werden. Man kann damit neue Metazeichen und Features in den Regex-Dialekt von Perl einbauen. Perl hat beispielsweise keine besonderen Metazeichen für den Wortanfang und das Wortende (nur eines für die Wortgrenze), aber manchmal wären \< und \> wie in anderen Dialekten schon sehr praktisch. Mit dem Regex-Overloading kann man diese Sequenzen hinter den Kulissen in Ausdrücke verwandeln, die Perl schon kennt.

In der aktuellen Implementation gibt es einige Beschränkungen, die die Nützlichkeit von überladenen Regex-Literalen doch ziemlich begrenzen. Diese Beschränkungen und Beispiele wie die mit \< und \> behandeln wir weiter unten in diesem Abschnitt.

Beim Umgang mit Code-Konstrukten (mit dem dynamischen Regex-Konstrukt oder mit dem Codemuster-Konstrukt) ist es sinnvoll, zunächst nur globale Variablen zu verwenden, bis die komplizierten Zusammenhänge mit my-Variablen klar geworden sind (siehe Vorsicht bei my-Variablen in Codemustern).

  

  

<< zurück vor >>

 

 

 

Tipp der data2type-Redaktion:
Zum Thema Reguläre Ausdrücke bieten wir auch folgende Schulungen zur Vertiefung und professionellen Fortbildung an:
   

Copyright der deutschen Ausgabe © 2008 by O’Reilly Verlag GmbH & Co. KG
Für Ihren privaten Gebrauch dürfen Sie die Online-Version ausdrucken.
Ansonsten unterliegt dieses Kapitel aus dem Buch "Reguläre Ausdrücke" denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.

O’Reilly Verlag GmbH & Co. KG, Balthasarstr. 81, 50670 Köln