10 Reguläre Ausdrücke - LUIS · Kapitel 10 • Reguläre Ausdrücke Das einfachste Beispiel für...

16
Kapitel 10 Reguläre Ausdrücke 10 Reguläre Ausdrücke Muster, nach denen zum Beispiel Dateien durchsucht werden sollen, können mit Hilfe von re- gulären Ausdrücken gebildet werden. engl.: Muster = pattern; regulärer Ausdruck = regular expression Ein regulärer Ausdruck wird durch normale Zeichen und Metazeichen gebildet. Nach den nor- malen Zeichen wird literal gesucht, wobei die Metazeichen dazu dienen, um nach bestimmten Zeichenkonstruktionen, Kombinationen bzw. Anordnungen zu suchen. Reguläre Ausdrücke bieten somit ein mächtiges und leistungsfähiges Werkzeug zum Suchen und Ersetzen. Jede Mi- nute, die man in Reguläre Ausdrücke investiert, zahlt sich vielfach aus! Reguläre Ausdrücke können bei UNIX in einer ganzen Reihe von Programmen verwendet werden: ed, sed, expr, grep, pg, vi, awk und vor allem bei allen gängigen Shells. In der Regel werden reguläre Ausdrücke benutzt, um Dateien nach dem Auftreten bestimmter Inhalte zu durchsuchen oder generelle Ersetzungen vorzunehmen. Eine Zeile aus einem awk-Programm (awk ist ein UNIX-Tool) könnte eine Anweisung ent- halten, die schematisch so dargestellt werden kann: /regulärer_Ausdruck/ {Aktion} Damit wird in allen Zeilen, auf die der reguläre Ausdruck zutrifft, die in Klammern stehende Aktion durchgeführt. Die Zeilen können aus einer Datei stammen. Reguläre Ausdrücke werden bei Perl meist in der Form /regulärer_Ausdruck/ dargestellt. Ob eine Variable einen bestimmten Text enthält, kann mit der Bedingung $zeichenkette =~ /regulärer_Ausdruck/ analysiert werden. print "Bill ist dabei!\n" if ($string =~ /Bill/); Ist der Text Bill in der Variablen $string enthalten, dann ist die Bedingung erfüllt und eine Meldung wird ausgegeben. Nachfolgend wird erst das Bilden regulärer Ausdrücke erläutert, bevor die Operatoren vorgestellt werden, die diese verwenden. 10.1 Metazeichen Für die Bildung von regulären Ausdrücken stehen folgende Metazeichen zur Verfügung: \ Entwertet das nächste Zeichen ^ Steht für Zeilenanfang . Beliebiges Zeichen (außer Zeilenvorschub) $ Steht für Zeilenende (oder vor dem Zeilenvorschub) | Alternative () Gruppierung [] Zeichenklasse 69

Transcript of 10 Reguläre Ausdrücke - LUIS · Kapitel 10 • Reguläre Ausdrücke Das einfachste Beispiel für...

Kapitel 10 • Reguläre Ausdrücke

10 Reguläre Ausdrücke

Muster, nach denen zum Beispiel Dateien durchsucht werden sollen, können mit Hilfe von re-gulären Ausdrücken gebildet werden.

engl.: Muster = pattern; regulärer Ausdruck = regular expression

Ein regulärer Ausdruck wird durch normale Zeichen und Metazeichen gebildet. Nach den nor-malen Zeichen wird literal gesucht, wobei die Metazeichen dazu dienen, um nach bestimmtenZeichenkonstruktionen, Kombinationen bzw. Anordnungen zu suchen. Reguläre Ausdrückebieten somit ein mächtiges und leistungsfähiges Werkzeug zum Suchen und Ersetzen. Jede Mi-nute, die man in Reguläre Ausdrücke investiert, zahlt sich vielfach aus!

Reguläre Ausdrücke können bei UNIX in einer ganzen Reihe von Programmen verwendetwerden: ed, sed, expr, grep, pg, vi, awk und vor allem bei allen gängigen Shells.In der Regel werden reguläre Ausdrücke benutzt, um Dateien nach dem Auftreten bestimmterInhalte zu durchsuchen oder generelle Ersetzungen vorzunehmen.Eine Zeile aus einem awk-Programm (awk ist ein UNIX-Tool) könnte eine Anweisung ent-halten, die schematisch so dargestellt werden kann:

/regulärer_Ausdruck/ {Aktion}

Damit wird in allen Zeilen, auf die der reguläre Ausdruck zutrifft, die in Klammern stehendeAktion durchgeführt. Die Zeilen können aus einer Datei stammen. Reguläre Ausdrücke werdenbei Perl meist in der Form /regulärer_Ausdruck/ dargestellt. Ob eine Variable einenbestimmten Text enthält, kann mit der Bedingung

$zeichenkette =~ /regulärer_Ausdruck/

analysiert werden.

print "Bill ist dabei!\n" if ($string =~ /Bill/); Ist der Text Bill in der Variablen $string enthalten, dann ist die Bedingung erfüllt und eineMeldung wird ausgegeben. Nachfolgend wird erst das Bilden regulärer Ausdrücke erläutert,bevor die Operatoren vorgestellt werden, die diese verwenden.

10.1 Metazeichen

Für die Bildung von regulären Ausdrücken stehen folgende Metazeichen zur Verfügung:

\ Entwertet das nächste Zeichen

^ Steht für Zeilenanfang

. Beliebiges Zeichen (außer Zeilenvorschub)

$ Steht für Zeilenende (oder vor dem Zeilenvorschub)

| Alternative

() Gruppierung

[] Zeichenklasse

69

Kapitel 10 • Reguläre Ausdrücke

Das einfachste Beispiel für einen regulären Ausdruck ist eine Zeichenkette. Wenn mehrereZeichen oder Teilausdrücke hintereinander stehen, müssen diese auch in der Reihenfolgeerkannt werden. Beim Muster

/Heino/

gibt es nur einen Treffer, wenn die Zeichenkette auch den Teilstring Heino enthält.Metazeichen müssen entwertet werden, um literal nach ihnen zu suchen. Damit sind folgendeZeichen zu entwerten, um sie literal zu benutzen: \ | ( ) [ ] { } ^ $ * ? . +

/\?/

Literale Zeichen werden durch den umgekehrten Schrägstrich in Metazeichen bzw.Sonderzeichen umgewandelt.

/\b\t\s\r/

Der . ist ein Platzhalter für ein beliebiges Zeichen: Buchstabe, Ziffer, Leerzeichen, Tabulatoroder sonstige Sonderzeichen außer dem Zeilenvorschub.Folgender regulärer Ausdruck sucht nach einem P gefolgt von zwei beliebigen Zeichen unddann einem l. Damit passt der Ausdruck zum Beipiel auf: Perl, Pril, Pool, Paul,Paulchen, Philipp, Philadelphia, Philosoph

/P..l/

Das nachfoldende Suchmuster trifft bei allen Zeichenketten außer bei einem leeren String:

/./

Eine Alternative zeigt der vertikale Balken an. Es wird ein Mitglied der Feuersteins gesucht:

/Fred|Wilma|Barney|Betty/

Runde Klammern dienen zur Gruppierung unterschiedlichster Art. Mit einer Gruppierungalternativer Teilstrings lassen sich Montag und Freitag aus dem Kalender streichen:

/(Mon|Frei)tag/

Um eine Zeichenkette am Anfang und am Ende überprüfen zu können, werden die Zeichen ̂und $ verwendet.

/^"/ # Die Zeile beginnt mit Anführungszeichen/\.$/ # Die Zeile endet mit einem Punkt/^$/ # Leerzeile

Diese Zeichenklasse sucht einen Vokal:

/[aeiouAEIOU]/

Eine Zeichenklasse stellt immer nur genau ein Zeichen dar. Dies verdeutlicht die Suche nachzwei aufeinanderfolgenden Vokalen.

/[aeiouAEIOU][aeiouAEIOU]/

70

Kapitel 10 • Reguläre Ausdrücke

Mit dem Startwert, dem Endwert und dem Bindestrich dazwischen lassen sich Bereicheangeben.

/[A-ZÄÖÜ]/ # Großbuchstaben/[a-zäöüßA-ZÄÖÜ]/ # Alle Groß- und Kleinbuchstaben/[\0-\xFF] # Alle ASCII-Zeichen

Um eine Zeichenklasse zu komplementieren muss das Zeichen ̂ vor der Liste der Zeichen inder Zeichenklasse stehen.

/[^0-9]/ # Ein Zeichen, dass keine Ziffer ist

Das Zeichen ^ hat nur am Anfang einer Zeichenklasse eine Sonderbedeutung. Soll es in einerZeichenklasse literal verwendet werden, empfiehlt es sich, es nicht am Anfang zu setzen, da essonst entwertet werden muss.

/[abc^]/

Soll das Zeichen ] in einer Zeichenklasse literal verwendet werden, muss dieses entwertet wer-den. Das Zeichen - ist bei der literalen Suche zu entwerten, wenn dieses einen Bereich angebenkönnte. Andere Metazeichen von regulären Ausdrücken verlieren ihre Sonderbedeutung inner-halb von eckigen Klammern.

/[\]\-\\[(){}^*+?.]/ # Nur die ersten drei Zeichen müssen entwertet werden/[a\-b][ab-][-ab]/ # Alle drei Zeichenklassen sind identisch

Weil häufig nach einer bestimmten Klasse von Zeichen gesucht werden muss, sind inPerl die wichtigsten gebräuchlichen Zeichenklassen bereits vordefiniert.

Definition Zeichen NegationWhitespace30 [ \t\n\r\f] \s \S

Wortzeichen, außer Um-laut und ß

[a-zA-Z_0-9] \w \W

Ziffer [0-9] \d \D

Die Negation der Zeichenklasse stellt der entsprechende Großbuchstabe bereit. So prüft bei-spielsweise das \D auf ein Zeichen, das keine Ziffer ist.

10.2 Quantifikatoren

Weitere Metazeichen sind Quantifikatoren. Quantifikatoren bestimmen, wie oft sich etwaswiederholen darf, was vor ihm steht. Dies sind Atome (einzelne Buchstaben) oder Teilausdrü-cke. Dabei trifft zum Beispiel der Quantifikator * auch bei 0 Wiederholungen. Das heißt: DerAusdruck vor dem Quantifikator muss nicht auftauchen.

30 Es gibt keinen treffenden deutschen Begriff für Whitespace. Deshalb wird hier der englische verwen-det. Einfach erklärt sind Whitespaces alle Zeichen, die auf dem Papier nichts Sichtbares hinterlassen.

71

Kapitel 10 • Reguläre Ausdrücke

Perl kennt folgende Quantifikatoren:

* 0 oder mehrmals

+ 1 oder mehrmals

? 1 oder keinmal

{n} genau n-mal (Anzahl)

{min,} mindestens min-mal

{min,max} zwischen min- und max-mal

Anmerkung: Bei min > max bricht der Compiler mit einer Fehlermeldung ab.

Folgender regulärer Ausdruck erkennt ein Wort:

\w+

Telefonnummern mit mindestens vier, aber nicht mehr als sieben Ziffern:

\d{4,7}

Fünfstellige Postleitzahlen:

\d{5}

Minimum:

\d{4,}

Maximum:

\d{0,4}

Folgende Quantifikatoren sind identisch:

* {0,}

+ {1,}

? {0,1}

Vergleich zur Dateisubstitution der Bourne-Shell:

? genau ein beliebiges Zeichen

* 0 oder mehrere beliebige Zeichen

In erweiterten regulären Ausdrücken, die bei UNIX-Tools verwendet werden, steht das ? wiebei Perl für 0- oder 1-mal.

Beispiel für die Suche nach HTML-Tags in der Form <...>, also suchen nach einer öffnendenspitzen Klammer, danach mindestens ein Zeichen, das keine schließende spitze Klammer ist,gefolgt von einer spitzen schließenden Klammer.

/<[^>]+>/

72

Kapitel 10 • Reguläre Ausdrücke

10.3 Gruppierung und Rückwärtsreferenzen

Eine Gruppierung ist zum Beispiel notwendig, um eine Reihe hintereinanderstehender Atomezu quantifizieren.

/(abc){5}/ # Suche nach:abcabcabcabcabc

Die runden Klammern bewirken, dass die eingeschlossenen Ausdrücke den speziellen Varia-blen $1, $2, $3, $4 usw. und den Rückwärtsreferenzen \1, \2, \3, \4 usw. zugeordnetwerden. Die Rückwärtsreferenzierung mit dem \ erfolgt nur innerhalb des regulären Ausdrucks.Die Variablen $1, $2 usw. sind innerhalb des umschließenden Blocks31 oder bis zum nächstenTreffen eines regulären Ausdrucks gültig.

$_="Teil1:Teil2";print "$1\n" if /(Teil)1:(\1)2/; # Ausgabe von: Teil

/(Teil1):(Teil2)/; print "$1, $2\n"; # Ausgabe von: Teil1, Teil2

Um die Referenzierung des Ausdrucks zu unterbinden, bietet die erweiterte Syntax für reguläreAusdrücke das speicherlose Klammerpaar an: (?:regulärer_Ausdruck)

$_="Teil1:Teil2";/(?:Teil1):(Teil2)/; print "$1\n"; # Ausgabe von: Teil2

Die Rückwärtsreferenz eines gruppierten Teilausdrucks, dem ein Quantifikator folgt, wird be-stimmt durch den letzten Treffer.

"Eins Zwei" =~ /(\w)+/;print "\$1=$1\n"; # Ausgabe von: $1=s

Gruppierungen lassen sich auch schachteln. Auch hierbei erfolgt die Nummerierung der ge-fundenen Teilausdrücke von links nach rechts. Um die Nummerierung der Rückwärtsreferenzeneines komplizierten Ausdrucks zu ermitteln, zählt man einfach die öffnenden Klammern bisdorthin.

"Eins Zwei" =~ /((\w)+)/;print "\$1=$1 \$2=$2\n"; # Ausgabe von: $1=Eins $2=s

Generelle Arbeitsweise des Matchers

Im Standard-Modus bringt der Matcher so viele Zeichen in einem Ausdruck unter wie möglich.Das heißt: Je mehr Zeichen auf den Ausdruck passen, desto besser. Ist dann der reguläre Aus-druck erfüllt, beendet der Matcher die Arbeit. Der Matcher kann als gefräßig betrachtet werden.

Die Gefräßigkeit des Matchers lässt sich an einem Beispiel mit Gruppierung zeigen:

$_="Teil1:Teil2:Teil3";print $1 if /(.+):/; # Ausgabe von: Teil1:Teil2

Der zweite Doppelpunkt wird zur Deckung des Ausdrucks benutzt. Dies lässt sich mit dem

31 Statt in einem Block könnte der reguläre Ausdruck auch in einer Zeichenkette stehen, die evaluiertwird (eval-Zeichenkette).

73

Kapitel 10 • Reguläre Ausdrücke

Non-greedy-Operator (greedy=gefräßig) abstellen.

$_="Teil1:Teil2:Teil3";print $1 if /(.+?):/; # Ausgabe von: Teil1

Der Non-greedy-Operator, das ?, wird nach dem Symbol für die Wiederholung, in diesem Fallnach dem +, platziert.

Folgende Tabelle zeigt die möglichen Kombinationen von Quantifikatoren und dem Non-greedy-Operator (?):

*? 0 oder mehrmals, bei minimal benutzten Zeichen zum Erfüllen des regu-lären Ausdrucks

+? 1 oder mehrmals, bei minimal benutzten Zeichen zum Erfüllen des regu-lären Ausdrucks

?? muss nicht oder einmal vorhanden sein, bei minimal benutzten Zeichenzum Erfüllen des regulären Ausdrucks

{min,}? mindestens min-mal, bei minimal benutzten Zeichen zum Erfüllen des re-gulären Ausdrucks

{min,max}? zwischen min- und max-mal, bei minimal benutzten Zeichen zum Erfül-len des regulären Ausdrucks

10.4 Quoting-ähnliche Operatoren

Bei Perl sind die regulären Ausdrücke eng in die Sprache eingebunden. Das geschieht nicht mitBibliotheksfunktionen, sondern mit Operatoren, die diese verwenden. Dies ermöglicht einHöchstmaß an Funktionalität. Nach dem Vorstellen regulärer Ausdrücke sollen nun die Opera-toren dafür näher betrachtet werden. Die Bedingung $string =~ /regulärer_Ausdruck/ verwendet den Operator //. DieOperanden für diesen Operator sind der reguläre Ausdruck und der Suchtext, auf den jener an-gewendet wird. Dieser Operator zählt zu der Gruppe der quoting-ähnlichen Operatoren. DieserTerm erhält, wie im Kapitel Operatoren schon erwähnt, die höchste Priorität bei der Auswer-tung eines Ausdrucks.

74

Kapitel 10 • Reguläre Ausdrücke

10.4.1 Der Operator zur Mustersuche: // bzw. m//

Der Operator zum Suchen eines regulären Ausdrucks in einer Zeichenkette wird in der Literaturauch Pattern-Matching-Operator genannt. Die exakte Definition sieht folgendermaßen aus:

m/regulärer_Ausdruck/cgimosx/regulärer_Ausdruck/cgimosx

Die Buchstaben cgimosx, die am Ende stehen, sind Optionen. Diese werden auch Modifizie-rer oder Flags genannt. Auf diese Optionen wird am Ende dieses Abschnitts eingegangen.

Der Operator muss nicht immer den regulären Ausdruck in Schrägstrichen einschließen. Stehtein einleitendes m davor, kann der reguläre Ausdruck auch durch Zeichen, die keine alphanu-merischen Zeichen oder Whitespaces sind, oder von Klammerpaaren begrenzt werden.Beispiele zum Einschließen des regulären Ausdrucks mit der oder ohne die Option m:

/regulärer_Ausdruck/m#regulärer_Ausdruck#m(regulärer_Ausdruck)m{regulärer_Ausdruck}

Die Verwendung der Option m ist zum Beispiel dann sinnvoll, wenn eine Zeichenkette unter-sucht werden soll, in der die einzelnen Teilstücke durch / voneinander getrennt sind.

Variablen werden jedes Mal interpoliert, wenn ein Mustervergleich stattfindet:

$pattern = '\s(\w+)\s'; # Suche nach einem von Whitespaces/$pattern/; # eingeschlossenen Wort

Auch hier gibt es eine Ausnahme: Bei der Verwendung von ' als Trennzeichen erfolgt keineInterpolation.

Der Operator liefert im skalaren Kontext wahr (1) oder falsch ('') zurück. Wenn der Opera-tor nicht an eine Zeichenkette gebunden ist, wird in der Zeichenkette $_ gesucht:

$_ = "Ziege Katze Hund";print "$1" if /(Ziege)/;

Der Operator // lässt sich mit den Operatoren =~ und !~ an eine Zeichenkette binden:

$string = "Zu untersuchende Zeichenkette\n";if ($string =~ /Zu/) { print $string;}

Der Operator !~ arbeitet wie =~, nur dass der Rückgabewert negiert wird. Im Beispiel wird derreguläre Ausdruck durch die Zeichenkette Zu dargestellt. Diese Buchstabenkombination ist inder zu untersuchenden Zeichenkette enthalten. Die Bedingung im vorherigen Beispiel ist alsowahr, deshalb erfolgt das Ausgeben der Zeichenkette.

Wie immer ist die default-Variable $_. Dies ist auch bei der Funktion print so. Perl ist soaufgebaut, dass alles möglichst kurz geschrieben werden kann. Das sollen folgende Beispieleverdeutlichen.

75

Kapitel 10 • Reguläre Ausdrücke

Wie im vorherigen Beispiel soll die Zeichenkette ausgegeben werden:

$_="Zu untersuchende Zeichenkette\n";if (/Zu/) { print;}# Oder noch kürzer:print if /Zu/;

Im Listen-Kontext liefert der Operator eine Liste zurück, die aus den in runden Klammern ein-geschlossenen Teilausdrücken des regulären Ausdrucks besteht.

($wort1, $wort2, $etc) = "Erste. Zweite. Rest des Strings" =~ /^(\S+)\s+(\S+)\s*(.*)/;print "$wort1\n$wort2\n$etc\n"; # Ausgabe von: # Erste.# Zweite.# Rest des Strings

Trifft der reguläre Ausdruck nicht, wird eine leere Liste zurückgegeben. Trifft der reguläreAusdruck, ist aber keine Gruppierung darin, wird die Liste (1) zurückgegeben.

($was_suche_ich_eigentlich) = "Erste. Zweite. Rest des Strings." =~ /\S+/;print "$was_suche_ich_eigentlich\n"; # Ausgabe von: 1

10.4.1.1 Optionen

Eine kurze Erläuterung zu den Optionen enthält nachfolgende Tabelle:

Option Beschreibung

c Verändert nicht die Suchposition bei Misserfolg und Verwendung der Option g

g Sucht nach jedem Vorkommen des Suchmusters in einer Zeile, also nicht nurnach dem ersten Vorkommen (global search)

i Führt die Muster-Suche durch, ohne dabei Groß- und Kleinschreibung zu un-terscheiden (case insensitive search)

m Behandelt die Eingabe als mehrzeilige Zeichenkette (multiple lines)

o Liest den als Suchmuster angegebenen regulären Ausdruck nur einmal(compile pattern once)

s Behandelt die Eingabe als einzeilige Zeichenkette (single)

x Verwendet erweiterte reguläre Ausdrücke (extended regular expressions)

Die Option x wird auch als Modifizierer für reguläre Ausdrücke benutzt, um die Lesbarkeit desMusters durch Leerzeichen und Kommentare zu erhöhen. Somit erfüllt x zwei Funktionennämlich, das Einfügen von Leerzeichen und Kommentaren sowie das Interpretieren von erwei-terten regulären Ausdrücken beim Operator //.

76

Kapitel 10 • Reguläre Ausdrücke

Die Option s

Zum Untersuchen einer Zeichenkette, die sich über mehrere Zeilen erstreckt, ist die Option serforderlich. Die Zeichenkette wird als eine Zeile behandelt. Das Metazeichen . trifft dann auchauf \n.

" behandeln der Rückwärtsreferenzierung behandeln der Option s" =~ /(\w+).*\s\1\s/s; # suche nach: Wort, evtl. beliebiger Text, selbes Wort in# Whitespaces eingeschlossen

printf 'Das Wort "%s" wurde wiederholt.' . "\n", $1;# Ausgabe von: Das Wort "behandeln" wurde wiederholt.

Die Option m

Im Normalfall bezeichnet $ das Ende einer Zeichenkette ohne das abschließende Newline-Zeichen.Soll aber in einer mehrzeiligen Zeichenkette $ das Ende einer Zeile repräsentieren, muss dieOption m verwendet werden.

" behandeln der Rückwärtsreferenzierung behandeln der Option m" =~ /(ung$)/m;print "$1\n"; # Ausgabe von: ung

Das Beispiel liefert nur mit der Verwendung der Option m einen Treffer, ansonsten müsste nachung\n gesucht werden.

Die Option x (Kommentare)

In einer while-Schleife steht zum Beispiel eine Zeile, die diese beendet, wenn eine Leerzeileoder eine Zeile nur mit Whitespaces eingelesen wird.

while(...){ ... last if /^\s*$/; ...}

Um eine bessere Lesbarkeit des Programms zu erhalten, soll die Zeile in der while-Schleife mitKommentaren versehen werden. Dazu ist die Option x der regulären Ausdrücke zu verwenden.

while(...){ ... last if m(

^ # Zeilenanfang \s* # Kein oder beliebig viele Whitespaces $ # Zeilenende

)x; # Der Modifizierer x gestattet Kommentare ...}

77

Kapitel 10 • Reguläre Ausdrücke

Option g im skalaren Kontext

Bei der Verwendung der Option g in einem skalaren Kontext wird bei jeder erneuten Ausfüh-rung die nächste Übereinstimmung gefunden.

z. B.: while ($string =~ /regulärer Ausdruck/g)

Bei einem Treffer ist der Rückgabewert wahr. Die Position des letzten Treffers kann mit derFunktion pos angezeigt werden.

$string="123g 134gooo";

print "Der Buchstabe \"g\" befindet sich auf den Positionen: ";while($string =~ /g/g) { print pos($string)." ";}print "\n";

Ausgegeben wird:

Der Buchstabe "g" befindet sich auf den Positionen: 4 9

Trifft der reguläre Ausdruck nicht zu, wird die Suchposition auf den Zeichenkettenanfanggesetzt. Dies kann durch die Option c verhindert werden.

$_="123g 134gooo";

/g/g;print pos, "\n";/z/g; # Der reguläre Ausdruck trifft nicht, kein z in $_/g/g;print pos, "\n\n";

$_="123g 134gooo";

/g/gc;print pos, "\n";/z/gc; # Der reguläre Ausdruck trifft nicht, kein z in $_/g/gc;print pos, "\n";

Ausgegeben wird:

44

49

Beispiel für die Option g im Listen-Kontext

$_ = "gg";($str1, $str2) = /g/g;printf "$str1, $str2\n"; # Ausgabe von: g, g

78

Kapitel 10 • Reguläre Ausdrücke

10.4.2 Der Substitutionsoperator: s///

s/regulärer_Ausdruck/Ersetzung/egimosx

sucht einen regulären Ausdruck in einer Zeichenkette. Wenn dieser gefunden wird, wird erdurch den Ersetzungstext ersetzt und die Anzahl der Ersetzungen wird zurückgegeben. An-dernfalls wird eine leere Zeichenkette (logisch falsch) zurückgegeben. Wie schon beim Operator // kann auch dieser Operator durch =~ oder !~ an eine Zeichenkettegebunden werden, ansonsten wird in $_ gesucht und ersetzt.

$_ = "new car";s/new/old/; # operiert auf $_

$string = "old car"; $string =~ s/old/new/; # operiert auf $string

print "$_, $string\n"; # Ausgabe von: old car, new car

Was wird zurückgegeben?

$_ = "old";print s/old/new/, "\n"; # Ausgabe von: 1

$string = "old";$a = $string !~ s/old/new/;print ">$a<\n"; # Ausgabe von: ><

Wie an dem Beispiel zu sehen ist, wird bei dem Operator !~ beim Treffen des Musters nichtdie Anzahl der Substitutionen zurückgegeben, sondern die leere Zeichenkette. Der Wahrheits-wert wird negiert.

Auch beim Substitutionsoperator muss der Schrägstrich nicht das Trennzeichen sein. Es lassensich auch andere Zeichen oder Klammerpaare verwenden. Trennzeichen dürfen alle nicht alpha-numerischen Zeichen sein. Ausgenommen sind Whitespaces als Trennzeichen. Wenn das Such-muster von Klammerpaaren begrenzt wird, hat die Ersetzung ein eigenes Paar von Trennzei-chen. Diese müssen nicht Klammerpaare sein.

$path =~ s#/freeware/bin#/usr/local/bin#;s(old)(new);s(old)[new];s<old>/new/;

Variable werden interpoliert. Es sei denn das Trennungszeichen ist '.

$Muster='.ld'; $Ersatz=new;s/$Muster/$Ersatz/; # äquivalent zu: s/.ld/new

Die Flags imosx haben dieselbe Bedeutung wie beim Operator m//. Lediglich das e-Flagbedarf einer Erklärung. Das Flag g wird an einem Beispiel gezeigt.

Die Option e

Die Option e bewirkt die Interpretation der Ersetzung als Perl Ausdruck. Die Ersetzung wirderst durch die Funktion eval() ausgeführt, bevor sie für den regulären Ausdruck eingesetztwird.

79

Kapitel 10 • Reguläre Ausdrücke

Die Zeichenkette abc wird durch den Rückgabewert des Unterprogramms ersetzt:

sub funk1 { return "123";}

$_='abc';s/abc/funk1()/e;print "$_\n"; # Ausgabe von: 123

Ausgeben einer Zufallszahl:

$_ = "Zufallszahl: rand\n";s/rand/int(rand(5))/e; # int() und rand() sind Perl-Funktionenprint;

$& ist eine spezielle Variable für reguläre Ausdrücke. Sie enthält den letzten Treffer eines re-gulären Ausdrucks.

$_='abc123xyz';/123/;print "$&\n"; # Ausgabe von: 123

$_='abc123xyz';s/\d+/$&*2/e; # liefert für $_ : abc246xyz

Die Option g

$_='alt alt alt';$Anzahl = s/alt/neu/;print "$_, Die Anzahl der Ersetzungen ist $Anzahl\n";

# Ausgabe von: neu alt alt, Die Anzahl der Ersetzungen ist 1

$_='alt alt alt';$Anzahl = s/alt/neu/g;print "$_, Die Anzahl der Ersetzungen ist $Anzahl\n";

# Ausgabe von: neu neu neu, Die Anzahl der Ersetzungen ist 3

10.4.2.1 $n statt \n

Bei der Rückwärtsreferenzierung ist auf der rechten Seite des Substitutionsoperators dieSchreibweise $n der Schreibweise \n vorzuziehen. Gemeint ist hier: $1, $2 ... ist statt \1, \2 ... zu verwenden. Die Ersetzung wird als eine in Anführungszeichen stehende Zeichenkette betrachtet. $n ist da-her eindeutiger. Besonders bei der Verwendung der Option e werden Schwierigkeiten vermie-den.

80

Kapitel 10 • Reguläre Ausdrücke

Nachfolgendes Beispiel zeigt, dass beim Ausführen eines Perl-Skripts mit der Option w,welches die Schreibweise \n verwendet, eine Warnung ausgegeben wird.

#!/usr/bin/perl -w$_='alf';s/(\w+)/\1\1/;print "$_\n";

Meldungen auf dem Bildschirm beim Ausführen des Skripts:

\1 better written as $1 at ./warn line 3.\1 better written as $1 at ./warn line 3.alfalf

Die nachfolgenden zwei Beispiele zeigen Fälle, bei denen die Verwendung der Schreibweise\n nicht zum gewünschen Ziel führt.

$_="8 ** 2 ist gleich: ";s/(\d)(.+)/$1 . $2 . $1 ** 2/e;print "$_\n"; # Ausgabe von: 8 ** 2 ist gleich: 64

Bei dem Ausdruck

s/(\d)(.+)/\1 . \2 . \1 ** 2/e;

würde \ als Operator zum Anlegen einer Referenz interpretiert werden.

$_="Betrag: 62T€";s/(\d+)T€/${1}000,00 €/;print "$_\n"; # Ausgabe von: Betrag: 62000,00 €

Nicht funktionieren würde,

$_="Betrag: 62T€";s/(\d+)T€/\1000,00 €/;print "$_\n"; # Ausgabe von: Betrag: @0,00 €

da \100 in einer Zeichenkette das Zeichen mit dem oktalen ASCII-Wert 100 ist. Den oktalenASCII-Wert 100 hat das Zeichen @. Auch durch geschweifte Klammern lässt sich das Problemin dieser Form (Schreibweise \n) nicht lösen:

/(\d+)T€/\{1}000,00 €/; # Betrag: {1}000,00 €/(\d+)T€/{\1}000,00 €/; # Betrag: {62}000,00 €

81

Kapitel 10 • Reguläre Ausdrücke

10.4.3 Der Transliterationsoperator: tr/// bzw. y///

tr/Zeichenfolge/Ersetzungsliste/cdsy/Zeichenfolge/Ersetzungsliste/cds

Dieser Operator verwendet keine regulären Ausdrücke. In der Literatur wird er aber meist nachden Operatoren m// und s/// erwähnt, da er auch einen quoting-ähnlichen Operator darstellt.Jedes Vorkommen eines Zeichens aus Zeichenfolge wird mit dem korrespondierenden Zeichenaus Ersetzungsliste ersetzt. Anders gesagt: Transliteriert der Operator jedes Vorkommen einesZeichen in Zeichenfolge mit dem entsprechenden Zeichen in Ersetzungsliste. Das erste Zeichenin Zeichenfolge wird mit dem ersten Zeichen von Ersetzungsliste ersetzt, usw.Der Rückgabewert ist die Anzahl der ersetzten oder gelöschten Zeichen.y ist ein Synonym für tr in Anlehnung an das UNIX-Kommando sed. y ist ein sed-Kommando,das auch eine Transliteration bewirkt. Selbst tr gibt es auch als UNIX-Kommando.Wie üblich arbeitet der Operator auf $_, wenn er nicht über =~ oder !~ an eine Zeichenkettegebunden wird.Ein Zeichenbereich kann mit einem Bindestrich angegeben werden:

tr/A-J/0-9/

macht dieselbe Ersetzung wie

tr/ACEGIBDFHJ/0246813579/

Wenn die Zeichenfolge von Klammerpaaren begrenzt wird, kann die Ersetzungsliste ihr eigenesPaar von Trennzeichen haben:

tr[A-Z][a-z]tr[A-Z]/a-z/tr#A-Z#a-z#

Option Bedeutung

c Komplement der Zeichenfolge

d Lösche nicht ersetzte Zeichen

s Nach der Ersetzung gleiche aufeinanderfolgende Zeichen zu einem verkürzen

Bei der Option d wird jedes Zeichen gelöscht, das in der Zeichenfolge steht, aber keinen Ersatzin der Ersetzungsliste hat. Andernfalls wird die Option d nicht verwendet und ist dieErsetzungsliste kürzer als die Zeichenfolge werden die fehlenden Zeichen mit denentsprechenden aus der Zeichenfolge aufgefüllt. Bei einer leeren Ersetzungsliste wird dieZeichenfolge dupliziert. Dies ist nützlich zum Zählen von Zeichen oder Verkürzen gleicheraufeinanderfolgender Zeichen.

$_='BOOK';tr/A-Z/A-Z/s; # BOOK → BOK

macht dasselbe wie:

tr/A-Z//s;

$_='BOOK';tr/OK//d; # BOOK → B

$count = tr/*/*/; # zählt die Sterne in $_

82

Kapitel 10 • Reguläre Ausdrücke

Der Modifizierer c bewirkt die Komplementierung der Zeichenfolge. Die komplementierteZeichenfolge enthält dann alle Zeichen außer den in der ursprünglichen Zeichenfolge angege-benen Zeichen. Anschließend erfolgt die Ersetzung.

tr/a-zA-Z/ /cs; # wandelt alle Zeichen, die keine Buchstaben sind, # in ein Leerzeichen

$_="Schreibe jedes Wort auf eine Zeile!";tr/a-zA-Z/\012/cs;print "$_";

Erzeugt folgende Ausgabe:

SchreibejedesWortaufeineZeile

10.5 Übung

1. AufgabeEntfernen Sie aus einer unter Windows erstellten Text-Datei die Carriage Return (Wagen-rücklauf) am Zeilenende, um diese Datei an UNIX anzupassen. (CR/LF ->LF) Für das UNIXBetriebssystem sind diese Zeichen redundant. Scheiben Sie dazu einen Filter. Das heißt, dasProgramm liest von der Standard-Eingabe und schreibt auf die Standard-Ausgabe.

2. AufgabeSchreiben Sie einen Filter, der umgekehrt wie in Aufgabe 1 arbeitet. Für eine von UNIXstammende Text-Datei sollen für Windows die Carriage Return (am Zeilenende) eingefügtwerden.

83

Kapitel 10 • Reguläre Ausdrücke

84