Reguläre Ausdrücke sind das wahrscheinlich mächtigste Werkzeug in Perl. Mit diesen regulären Ausdrücken kann man Skalare relativ einfach nach bestimmten Zeichen oder Zeichenketten durchsuchen, man kann aber auch relativ einfach einzelne Zeichen oder Zeichenketten austauschen, löschen oder einfügen.
Wie sie vielleicht merken, sage ich immer relativ einfach. In Wahrheit braucht es einiges an Zeit und Übung, bis man sich an den Syntax gewöhnt hat.
Aber fangen wir einfach mal von vorne an:
Einfache Zeichensuche
Wir fangen mit dem einfachsten Beispiel an, der Suche nach EINEM BESTIMMTEN Zeichen:
Wie Sie vielleicht schon wissen, ist der reguläre Ausdruck das "~ /e/".
Aber was bedeutet das nun?
Also, das =~ / bedeutet "suche nach", und zwar nach dem, was zwischen den beiden // steht, also dem kleinen e, und auch nur danach.
Da das e in Test vorhanden ist, wird vom Script ein "wahr" ausgegeben. Ein "falsch" wäre ausgegeben worden, wenn $t="TEST" gewesen wäre, also das E gross geschrieben.
Diese Schreibweise findet also genau das, und nur das, was zwischen den beiden // steht!
Natürlich könnte man zwischen die beiden // noch andere Sachen setzen, beliebig viele Buchstaben oder Ziffern oder Sonderzeichen.
Dieses Skript liefert nur in den ersten beiden Tests "wahr", im dritten Test ein falsch, da der maurer ja klein geschrieben (also falsch) ist.
So weit, so einfach, so gut!
Aber jetzt gehts schon los mit den Besonderheiten:
Einige Zeichen können nicht ohne weiteres verwendet werden, da sie von den regulären Ausdrücken selbst verwendet werden, nämlich als Steuerzeichen. Gesehen hat man das ja schon an dem /-Zeichen.
Die Zeichen, die nicht einfach so verwendet werden dürfen, sind die Zeichen
. ? * + ^ $ | \ / ( ) [ ] { } ; #
sowie jeweils das Zeichen, das als "Klammer" um den regulären Ausdruck verwendet wird (im Allgemeinen meistens der Schrägstrich "/").
Will man nach diesen Zeichen suchen, so muß man einen Backslash ("\") voranstellen, wie in folgendem Beispiel:
$t="Reguläre Ausdrücke können auch kompliziert sein...";
if( $t=~ /\.\.\./){ print "wahr\n" } else { print "falsch\n" } # Test 1
if($t=~ /\./) { print "wahr\n" } else { print "falsch\n" } # Test 2
if($t=~ /./) { print "wahr\n" } else { print "falsch\n" } # Test 3
Diese Tests liefern alle "wahr".
Test 1 findet tatsächlich die drei Punkte am Ende. Test 2 findet den ersten der drei Punkte, Test 3 findet das R am Anfang.
Für einige häufig gebrauchte Zeichen, die sich schlecht direkt darstellen lassen, gibt es besondere Symbole (siehe auch unter Stringkonstanten):
Übrigens lassen sich alle Zeichen auch als Oktal-Code angeben. Schreiben Sie dazu den ASCII-Code in Oktal mit einem Backslash davor, also zum Beispiel \101 für das "A". Achtung: Es müssen immer drei Stellen sein, auch wenn sie nicht erforderlich zu sein scheinen, wie zum Beispiel bei 005!
Ich möchte an dieser Stelle nochmals auf die ganz besondere Bedeutung des Punktes . eingehen.
Der . kann jedes beliebige Zeichen darstellen, einzige Ausnahme ist der Zeilenvorschub \n.
Diese Fähigkeit macht den . sehr wichtig für reguläre Ausdrücke.
$t="Der Punkt als Universalzeichen";
if($t =~ /P...t/) { print "wahr\n" } else { print "falsch\n" } # Test 1
Ergibt ein wahr, da im Wort Punkt zwischen P und t drei beliebige Zeichen stehen. Gefunden werden würde auch "Paket" oder "Puket", nicht aber "Pakt" (nur zwei Zeichen) zwischen P und t, oder "punkt" (Kleinschrift!).
Wie wir später sehen werden kann der Punkt sehr hilfreich sein, wenn es um das Ersetzen von Zeichen geht.
Was fällt mir dazu noch ein?
Yo, folgendes:
Das Suchen kann auch folgendermaßen durchgeführt werden:
$t="Noch eine Suchart";
$s="eine";
if ($t=~/$s/){print "wahr";} else {print "falsch";}
Das, was gesucht wird, steht also selbst in einem Skalar. Das hat natürlich den Vorteil, daß man nicht jedesmal ein RegEx für jede Suche schreiben muß.
$t="Noch eine Suchart";
$s=".";
if ($t=~/$s/){print "wahr";} else {print "falsch";}
Ausgabe: wahr
Der . in $s findet das "N" am Anfang.
So und jetzt was zur allgemeinen Verwirrung:
#Beispiel 1
$t="Noch eine Suchart";
$s="\.";
if ($t=~/$s/){print "wahr";} else {print "falsch";}
Man könnte meinen, daß jetzt nach dem richtige, echten, einzig wahren . gesucht wird, aber falsch gedacht, gefunden wird wieder das "N".
Erst mal der Beweis dafür: (ich muß da allerdings etwas vorgreifen auf Sachen, die ich noch nicht erklärt habe)
$t="Noch eine Suchart";
$s="\.";
if ($t=~ /($s)/){print "wahr, gefunden wurde $1";} else {print "falsch";}
Wieso? Also, $s="\." bedeutet für Perl: Verarbeite das, was zwischen den beiden " steht und weise es $s zu.
In diesem Fall bedeutet das: \. ist der Punkt, und dieser Punkt wird $s zugewiesen! Also ist $s="\." equivalent zu $s="."
Beweis:
$t="Noch eine Suchart";
$s="\.";
if ($t=~ /($s)/){print "wahr, gefunden wurde $1\n";} else {print "falsch\n";}
#hier wird $s genauer untersucht print "Inhalt von \$s: $s \nLaenge von \$s: ".length($s)." Zeichen";
Ausgabe unten: Laenge von $s=1, Inhalt = .
Jetzt wird auch klar, warum das Beispiel oben (Beispiel1) das N gefunden wird!
Ja, kann man sagen, das ist ja schön, aber wenn ich nun wirklich nur den Punkt, und nur den(!) finden will?
Dann kann man den Punkt folgendermaßen codieren:
$t="Noch eine Suchart";
$s='\.';
if ($t=~ /($s)/){print "wahr, gefunden wurde $1\n";} else {print "falsch\n";}
#hier wird $s genauer untersucht print "Inhalt von \$s: $s \nLaenge von \$s: ".length($s)." Zeichen";
Ausgabe: falsch
laenge von $s: 2, Inhalt = \.
Wenn man also den Punkt als solchen suchen möchte, muß man die zu suchende Zeichenkette nicht zwischen "-Zeichen schreiben, sondern zwischen '-Zeichen!
Erklärung:
Zeichen zwischen '-Zeichen werden nicht evaluiert, sie werden also so übernommen, wie sie eingegeben werden!
So, das war's erstmal mit dem "einfachen" Suchen.
Weiter mit den Regulären Ausdrücken geht's demnächst hier.
Kommentare zum Beitrag "Reguläre Ausdrücke"
Kommentar von Hank
Ein Supertool zum Testen ist RegExr: http://schraegschrift.de/ online-regulaere- ausdruecke-testen/