Klammerung von Ausdrücken

[ <= ] [ PERL ] [ SUMMARY ] [ => ]

Im Abschnitt zur Mehrfachsuche wirkte eine entsprechende Anweisung immer nur auf das eine unmittelbar davor stehende Zeichen. Mit Hilfe von Klammern ("(...)") können auch längere Ausdrücke mehrfach gesucht werden.

Dazu ein Beispiel:

#!/usr/local/bin/perl -w

$t = "1.030303";

if($t =~ /03{2,3}/)   { print "true ($&)\n" } else { print "false\n" }  # Test 1
if($t =~ /(03){2,3}/) { print "true ($&)\n" } else { print "false\n" }  # Test 2

Test 1 liefert hier "false" (es wird nach einer '0' gefolgt von 2 oder 3 '3'en gesucht). Erfolgreich dagegen verläuft Test 2: er findet '030303' (längste Lösung).

Klammern bewirken auch noch einen Nebeneffekt: Derjenige Substring, der auf das Muster der ersten Klammer paßt, wird in die Variable $1 geschrieben, der zweite Substring in $2, usw. Zur Festlegung der Reihenfolge der Klammern zählt die jeweils öffnende Klammer (dies ist wichtig bei ineinander verschachtelten Klammerpaaren).

#!/usr/local/bin/perl -w

$t = "Breite: 7.5 m";

if($t =~ /(\w+): ([\d.]+ m)/) { print "true ($&)\n" } else { print "false\n" }

print "\$1: $1\n";
print "\$2: $2\n";

Auch dieser recht kompliziert aussehende reguläre Ausdruck läßt sich relativ einfach auflösen:

Somit enthält schließlich $1 den Wert 'Breite' und $2 den Wert '7.5 m'. Da alle Bedingungen der Suche erfüllt sind, ergibt sich natürlich der Gesamtwert "true".

Möchte man den Nebeneffekt der Zuweisung von $1, $2, $3,... verhindern, fügt man nach der öffnenden Klammer "?:" ein.

#!/usr/local/bin/perl -w

$t = "a b";

$t =~ /(.)\s(.)/;
print "\$1: $1\n";      # gibt 'a' aus

$t =~ /(?:.)\s(.)/;
print "\$1: $1\n";      # gibt 'b' aus

Im ersten Test werden sowohl $1 (mit 'a') als auch $2 (mit 'b') belegt. Im zweiten Test dagegen findet bei der ersten Klammer keine Zuweisung statt und der Inhalt der zweiten Klammer ('b') wird in $1 geschrieben.

Es ist sogar möglich, schon innerhalb des regulären Ausdrucks auf vorher im String gefundene Teilstrings zuzugreifen. So findet sich der Wert der ersten Klammer in \1, der der zweiten Klammer in \2, usw. Die Zuordnung ist identisch zu der von $1, $2, usw., allerdings dürfen die 'Backslash-Variablen' nur innerhalb des Suchmusters und die 'Dollar-Variablen' nur außerhalb verwendet werden.

#!/usr/local/bin/perl -w

$t = "abc--defg-h----ijk";

if($t =~ /(.{2}).+?\1/) { print "true ($&)\n" } else { print "false\n" }
print "\$1: $1\n";

Der reguläre Ausdruck sucht nach genau zwei gleichen Zeichen, die aber ansonsten beliebig gewählt sein können, gefolgt von einer möglichst kurzen Zeichenkette aus mindestens einem Symbol gefolgt von dem Zeichenpaar, das in der ersten Klammer gefunden wurde. Der gefundene Substring lautet dann '--defg-h--' und $1 enthält wie erwartet '--'.

Die Verwendung von \1, \2, usw. kann zu Problemen führen, wenn sich daran eine Suche nach Ziffern anschließt; eine mögliche Lösung ist die Benutzung von Klammern des Typs "(?:...)":

#!/usr/local/bin/perl -w

$t = "12--456--12";

if($t =~ /(--)\d+?\112/)     { print "true ($&)\n" }       # Test 1
                        else { print "false\n" }
if($t =~ /(--)\d+?(?:\1)12/) { print "true ($&)\n" }       # Test 2
                        else { print "false\n" }

Hier schlägt Test 1 fehl, da \112 als Oktal-Code interpretiert wird (Zeichen 'J'). Die zusätzliche Klammer in Test 2 sorgt für die korrekte Lösung ('--456--12').


[ <= ] [ PERL ] [ SUMMARY ] [ => ]

Autor: Eike Grote Letzte Änderung: 02.10.1997