Der Substitutionsoperator

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

Mit dem Substitutionsoperator von Perl, s/.../.../, wird die Idee der Mustererkennung um ein »Suchen und Ersetzen« erweitert. Die allgemeine Form ist:

SuchtextOperand =~ s/Regex/Ersatztext/Modifikatoren

Kurz gesagt wird dabei der Treffertext der Regex durch den Wert des Ersatztext-Operanden ersetzt. Wenn der /g-Modifikator verwendet wird, wird die Regex wiederholt angewendet und alle Treffer werden ersetzt.

Wie beim Match-Operator können der Suchtext-Operand und das verbindende =~ weggelassen werden, wenn im Standardsuchtext $_ substituiert werden soll. Das s am Anfang wird aber im Gegensatz zum m immer benötigt.

Wir haben gesehen, dass der Match-Operator ziemlich kompliziert ist – je nach Kontext verhält er sich anders oder gibt etwas anderes zurück. Er hängt von pos und von den Modifikatoren ab. Im Vergleich dazu ist die Substitution geradezu einfach: Der Rückgabewert ist immer gleich (und gibt an, wie oft etwas ersetzt wurde), und die Modifikatoren sind einfach verständlich.

Auch hier kann man die fünf allgemeinen Modifikatoren verwenden (siehe Regex-Modifikatoren), aber bei der Substitution gibt es zwei zusätzliche: den bereits bekannten /g-Modifikator und /e, der im übernächsten Abschnitt beschrieben wird.

Der Ersatztext-Operand

Bei der üblichen Form s/.../.../ folgt der Ersatztext direkt auf den Regex-Operanden und wird mit einem dritten Begrenzungszeichen abgeschlossen. Wenn klammerartige Begrenzer für die Regex verwendet werden (wie etwa <...>), dann steht der Ersatztext in seinem eigenen, unabhängigen Paar von Begrenzern (also gibt es insgesamt vier Begrenzungszeichen). Beispiele dafür sind s{...}{...} und s[...]/.../ sowie s<...>'...'. In diesem Fall können die Operanden durch Whitespace oder auch durch Kommentar-Zeilen getrennt sein. Mit /x oder /e werden häufig geschweifte Klammern verwendet:

$text =~ s{
  ... Große Regex mit eingestreuten Kommentaren ...
} {
  ... Perl-Code, der evaluiert wird; das Resultat wird als Ersatztext verwendet ...
}ex;

Unterscheiden Sie genau zwischen Regex und Ersatztext. Der Regex-Operand wird nach besonderen, auf reguläre Ausdrücke zugeschnittenen Regeln verarbeitet (siehe Begrenzungszeichen für den Regex-Operanden). Der Ersatztext-Operand wird wie ein String in Anführungszeichen geparst und ausgewertet. Diese Auswertung geschieht, nachdem die Mustersuche einen Treffer gefunden hat (bzw. mit /g nach jedem Treffer erneut), deshalb können im Ersatztext Variablen wie $1 verwendet werden, die sich auf den gerade gefundenen Treffer beziehen.

Nur in zwei Fällen wird der Ersatztext-Operand nicht wie ein String in Anführungszeichen verarbeitet:

  • Wenn der Ersatztext-Operand in Hochkommas eingefasst ist, wird er wie ein String in Hochkommas verarbeitet, es werden also keine Variablen interpoliert.
  • Mit dem Modifikator /e (siehe den nächsten Abschnitt) wird der Ersatztext-Operand wie ein Stück Perl-Code geparst und nicht wie ein String in Anführungszeichen. Dieses Codestück wird danach ausgeführt, und der Rückgabewert dieses Codes wird als Ersatztext verwendet.

Der /e-Modifikator

Mit dem /e-Modifikator wird der Ersatztext-Operand wie ein Stück Perl-Code behandelt, also wie mit einem eval {...}. Die Syntax wird zur Kompilationszeit des Perl-Skripts geprüft, aber der Code wird nach jedem Treffer neu ausgewertet. Der Code wird nach jeder Mustersuche in einem skalaren Kontext ausgewertet, und das Resultat dieser Auswertung wird zum Ersatztext. Hier sehen Sie ein einfaches Beispiel:

$text =~ s/-time-/localtime/ge;

Hier wird jedes Vorkommen von ˹-time-˼ durch den Rückgabewert der localtime-Funktion ersetzt, die im skalaren Kontext eine String-Darstellung der lokalen Zeit liefert, zum Beispiel »Mon Sep 25 18:36:51 2006«.

Weil der Code nach jedem Treffer neu ausgewertet wird, kann man im Codestück die Nebeneffekte ($1 usw.) des eben beendeten Matchings verwenden. Zum Beispiel kann man in einer URL Sonderzeichen, die vielleicht in einer URL nicht erlaubt sind, als zweistellige Hexadezimalzahl mit einem %-Zeichen davor codieren. Die folgende Substitution codiert alle nicht-alphanumerischen Zeichen in dieser Art:

$url =~ s/([^a-zA-Z0-9])/sprintf('%%%02x', ord($1))/ge;

Und mit dieser Substitution erhält man den ursprünglichen String zurück:

$url =~ s/%([0-9a-f][0-9a-f])/pack("C", hex($1))/ige;

sprintf('%%%02x', ord(Zeichen)) verwandelt, kurz gesagt, ein Zeichen in die numerische URL-Darstellung, und pack("C", Code) macht das Umgekehrte. Mehr dazu finden Sie in der Dokumentation zu Perl.

Mehrfacher Gebrauch von /e

Modifikatoren kann man auch doppelt und mehrfach angeben, das tut nichts zur Sache (außer dass es den Leser verwirren kann). Beim /e-Modifikator ist das anders: Normalerweise wird der Perl-Code evaluiert und das Resultat eingesetzt. Wenn aber ein zweites ›e‹ angegeben wird, wird das Resultat des Codestückchens erneut als Perl-Programm evaluiert. Das funktioniert mit so vielen eval-Zyklen, wie Sie ›e‹s angeben. Wirklich nützlich ist das nur für den Obfuscated Perl Contest. (Anmerkung: Ein Wettbewerb für das unleserlichste Perl-Programm; nach dem Wettbewerb für C, den es schon seit Jahren gibt. (Anm. d. Ü.))

In wenigen Fällen ist diese Möglichkeit auch für ganz gewöhnliche Zwecke einsetzbar. Wie würden Sie Variablen »von Hand« in einen String interpolieren – zum Beispiel in Strings, die aus einer Konfigurationsdatei eingelesen wurden? Gelesen wird ein String wie ›... $var ...‹, und der Substring ›$var‹ soll durch den Wert der Variablen $var ersetzt werden.

Ein einfacher Ansatz kann so aussehen:

$data =~ s/(\$[a-zA-Z_]\w*)/$1/eeg;

Ohne irgendein /e würde einfach der gefundene String ›$var‹ durch sich selbst ersetzt – das ist ziemlich nutzlos. Mit einem /e wird der Code in $1 ausgeführt, wir erhalten ›$var‹; d.h., es wird wieder der gefundene String durch sich selbst ersetzt – das ist genauso witzlos wie vorher. Mit dem zweiten /e allerdings wird ›$var ‹ erneut als Perl-Code interpretiert und ergibt diesmal den Wert der Variablen; dieser ersetzt den Namen. So kann man die Variableninterpolation nachahmen.

Kontext und Rückgabewert

Beim Match-Operator hängt die Art des Rückgabewerts vom Kontext und vom /g-Modifikator ab. Beim Substitutionsoperator ist das einfacher – er gibt immer die Anzahl der vorgenommenen Substitutionen zurück, und bei gar keiner Substitution den Leerstring.

Wenn dieser Rückgabewert in einem booleschen Kontext (wie im Bedingungsteil einer if-Anweisung) vorkommt, wird er praktischerweise als wahr interpretiert, wenn Ersetzungen vorgenommen wurden, und als falsch, wenn das nicht der Fall war.

  

<< 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