Besonders flexibel werden reguläre Ausdrücke durch die Möglichkeit, nach dem mehrfachen Auftreten von Zeichen zu suchen (wobei "mehrfach" auch "keinmal" einschließt).
Dies erfolgt im allgemeinsten Falle durch die Angabe eines Zahlenbereichs in
geschweiften Klammern. So bedeutet beispielsweise "{2,5}
", daß
das vorangehende Symbol 2,3,4 oder 5-mal auftreten darf.
Ein Beispiel:
#!/usr/local/bin/perl -w $t = "A----Z"; if($t =~ /-{1,3}/) { print "true ($&)\n" } else { print "false\n" } # Test 1 if($t =~ /-{2,6}/) { print "true ($&)\n" } else { print "false\n" } # Test 2 if($t =~ /-{5,10}/) { print "true ($&)\n" } else { print "false\n" } # Test 3 |
true
" aus. Hier ist das gefundene
Muster (in der Variablen $&
) von besonderem Interesse: es werden
drei Minuszeichen ausgegeben. Darin erkennt man eine wichtige Eigenschaft
der Suche nach mehrfachen Zeichen: Perl versucht, möglichst viele davon
zu finden. Dies sehen wir auch im zweiten Test: hier wird die Maximalzahl von
vier Minuszeichen als gefundener Substring ausgegeben. Dagegen liefert der
false
", da die Bedingung nicht einmal
durch die kleinste Zahl (5) erfüllt werden kann.
Da solche Mehrfachsuchen sehr häufig in Perl benutzt werden, gibt es einige Abkürzungen, die die Schreibarbeit vereinfachen (und auch zur Übersichtlichkeit beitragen):
Beispiele:
Abkürzung Entsprechung Bedeutung {
n}
{
n,
n}
genau n-mal {
n,}
mindestens n-mal ?
{
0,
1}
höchstens einmal +
{
1,}
mindestens einmal *
{
0,}
beliebig oft
#!/usr/local/bin/perl -w $t = "xxxAzz"; if($t =~ /x{2}/) { print "true ($&)\n" } else { print "false\n" } # Test 1 if($t =~ /x{2,}/) { print "true ($&)\n" } else { print "false\n" } # Test 2 if($t =~ /z+/) { print "true ($&)\n" } else { print "false\n" } # Test 3 if($t =~ /B?/) { print "true ($&)\n" } else { print "false\n" } # Test 4 if($t =~ /xAy*/) { print "true ($&)\n" } else { print "false\n" } # Test 5 if($t =~ /x*z+/) { print "true ($&)\n" } else { print "false\n" } # Test 6 |
Die Variable $t
besteht alle Tests erfolgreich; die folgende
Liste zeigt, an welchen Stellen jeweils der reguläre Ausdruck paßt
(Perl sucht hier immer die größtmögliche Lösung):
xxxAzz
(genau zwei aufeinanderfolgende "x
")
xxxAzz
(mindestens zwei aufeinanderfolgende "x
")
xxxAzz
(mindestens ein "z
")
xxxAzz
("B
" wird 0-mal "gefunden" - daher auch hier "true
")
xxxAzz
("x
" gefolgt von "A
" evt. gefolgt von "y
")
xxxAzz
(beliebig viele "x
" gefolgt von mindestens einem "z
")
Wenn gesagt wird, daß Perl die größtmögliche Lösung sucht, so ist dies eigentlich nicht ganz richtig; man sollte genauer sagen: die längste Lösung, die sich bei der Suche ab dem Startpunkt des vorgegebenen Strings ergibt. Eine Suche beginnt immer vor dem ersten Zeichen der zu durchsuchenden Zeichenkette. Wird, von dieser Startposition ausgehend, eine Lösung gefunden, so wird die Suche (erfolgreich) abgebrochen, auch wenn es vielleicht weiter hinten noch eine längere Lösung gäbe. Bei einem Fehlschlag beginnt eine erneute Suche ein Zeichen weiter hinten; dieses Verfahren wiederholt sich so lange, bis eine Lösung gefunden oder das Ende des Strings erreicht wird.
#!/usr/local/bin/perl -w $t = "aa==aaaa"; if($t =~ /a*/) { print "true ($&)\n" } else { print "false\n" } # Test 1 if($t =~ /=*/) { print "true ($&)\n" } else { print "false\n" } # Test 2 if($t =~ /=+/) { print "true ($&)\n" } else { print "false\n" } # Test 3 |
In
Die Problematik, daß Perl immer versucht, eine möglichst große
Lösung zu finden, wurde schon angesprochen. Dies ist bisweilen unerwünscht;
daher gibt es seit
{
n
,
m}?
{
n
}?
{
n
,}?
??
+?
*?
Ein Beispiel, das den Unterschied verdeutlicht:
#!/usr/local/bin/perl -w $t = "mmmmm"; if($t =~ /m+/) { print "true ($&)\n" } else { print "false\n" } # Test 1 if($t =~ /m+?/) { print "true ($&)\n" } else { print "false\n" } # Test 2 if($t =~ /m*?/) { print "true ($&)\n" } else { print "false\n" } # Test 3 |
Der erste Test gibt 'mmmmm' als (maximale) Lösung aus, während
Es sei hier noch erwähnt, daß beispielweise "m*?
"
keinesfalls immer automatisch null Zeichen bedeuten muß wie man nach dem
obigen Beispiel vielleicht zunächst glauben mag.
#!/usr/local/bin/perl -w $t = "AmmmAmmmA"; if($t =~ /Am*?A/) { print "true ($&)\n" } else { print "false\n" } # Test 1 if($t =~ /A.+A/) { print "true ($&)\n" } else { print "false\n" } # Test 2 if($t =~ /A.+?A/) { print "true ($&)\n" } else { print "false\n" } # Test 3 |
Hier enthält der gefundene Substring im
Autor: Eike Grote | Letzte Änderung: 02.10.1997 |