ein Kapitel zurück                                           ein Kapitel weiter

Die Metazeichen haben sie schon im ersten Kapitel der Regulären Ausdrücke kennen gelernt. Nun wollen wir das ganze ein bisschen vertiefen. Beginnen wollen wir mit dem Metazeichen und dem normalen Zeichen, dem Punkt "."
Sollten sie in einem Satz nach einem Punkt suchen wollen so müssen sie diesem einem Backslash "\" voranstellen...

#!/usr/bin/perl -w

use strict;

my $text = "Die Suche nach dem Punkt.";

if($text=~/\./){
   print "Punkt gefunden\n";
  }


Hätten sie stattdessen geschrieben...

if($text=~/./)   

...wäre die Ausgabe zwar auch Punkt gefunden, aber das Metazeichen "." bedeutet in diesem Fall ja das es sich um ein beliebiges Zeichen (außer newline) handelt.

Wenn sie nach einzelnen Zeichen suchen können sie diese in eckigen Klammern setzen...

#!/usr/bin/perl -w

use strict;

my $text = "Dieser Text enthaelt 1 Zahl.";

if($text=~/[0-9]/){
   print "Zahl gefunden\n";
  }


Sollten sie überprüfen wollen ob der Text ein Zeichen enthält das nicht in den eckigen Klammern steht, so brauchen sie dieses nur mit dem Zeichen ^ in den eckigen Klammern negieren...

#!/usr/bin/perl -w

use strict;

my $text = "12343535343566a798";

if($text=~/[^0-9]/){
   print "Ein Zeichen gefunden das keine Ziffer ist\n";
  }


Sie sehen das Zeichen ^ hat in eckigen Klammern ein andere Bedeutung als das Metazeichen ^ , was ja für das verankern eines Strings am Anfang steht.

Wenn sie nach Steuerzeichen suchen wollen, machen die ebenfalls am besten in eckigen Klammern...

#!/usr/bin/perl -w

use strict;

my $text = "Dieser Text\t enhält Steuerzeichen\n";
my $tab = "        ";
my $nwl = "<br>";

if($text=~/[\t\n]/){
   print "Steuerzeichen im Text gefunden\n";
   $text=~s/[\t]/$tab/;
   $text=~s/[\n]/$nwl/;
  }

print $text , "\n";


Ich benutze diese Programm in ähnlicher Weise und meinen Bedürfnissen angepasst um z.B. C-Programme in HTML-Format zu konvertieren.

Ein Hinweis noch zu dem Backslashing wie zum Beispiel...

/\/usr\/bin\/locale\/perl/  #/usr/bin/locale/perl      

...können sie anstatt den ständigen Backslashes die Zeichen zwischen den Metazeichen \Q....\E stellen...

/\Q/usr/bin/locale/perl\E/

Somit verliert jedes Metazeichen zwischen \Q und \E seine Bedeutung als Metazeichen.

Kommen wir nun zu den Zero-With-Assertion. Sogenannte Wortbegrenzer und deren Einsatzmöglichkeit...

#!/usr/bin/perl -w

use strict;

my $text = "wortgrenzen wort verantwortlich antwort ";
my @array=(0);
my $counter=0;

while($counter!=5){
  $array[$counter]=$text;
  $counter++;
 }

$array[0] =~ s/wort/----/g ;      #alle wort zu ----
$array[1] =~ s/wort\b/----/g;     #alle ....wort am Ende zu ----
$array[2] =~ s/\bwort\b/----/g#alle wort exakt zu ----
$array[3]=~ s/\bwort/----/g;      #alle wort.... am Anfang zu ----
$array[4]=~ s/\Bwort\B/----/g#alle ...wort... dazwischen zu ----

$counter=0;
  foreach(@array){
  print "$array[$counter]" , "\n";
  $counter++;
 }


Die Ausgabe sieht dabei folgendermaßen aus...

----grenzen ---- verant----lich ant----
wortgrenzen ---- verantwortlich ant----
wortgrenzen ---- verantwortlich antwort
----grenzen ---- verantwortlich antwort
wortgrenzen wort verant----lich antwort


In diesem Beispiel haben wir nur mit dem Wortbegrenzer \b und Nicht-Wortbegrenzer \B gearbeitet. 

Nehmen wir mal an sie wollen folgenden Text....

"Dieser Text besitzt\n zwei Newlinezeichen\n "

...zwischen...

>>>....<<<

....stellen. Wie würden sie vorgehen. Ihres Wissens nach wahrscheinlich so...

#!/usr/bin/perl -w

use strict;

my $text = "Dieser Text besitzt\n zwei Newlinezeichen\n ";
$text=~ s/^/>>>/mg;
$text=~s/$/<<</mg;
print $text, "\n";


Nun ja wenn man sich aber die Ausgabe ansieht...

>>>Dieser Text besitzt<<<
>>> zwei Newlinezeichen<<<
>>> <<<

Das Problem in diesem Beispiel ist das durch die Flags /mg die Bedeutung von $ so verändert wurde das \n das Ende des Strings darstellt. Und das ^ wird durch dieses Flag als Anfang einer jeden Zeile verwendet. Um dies zu vermeiden gibt es die beiden Metazeichen \A und \Z, für den Anfang und den Ende eines Strings vor den Newline am Ende...

#!/usr/bin/perl -w

use strict;

my $text = "Dieser Text besitzt\n zwei Newlinezeichen\n ";
$text=~ s/\A/>>>/mg;
$text=~s/\Z/<<</mg;
print $text, "\n";


Mit dieser Möglichkeit kommen wir dem Programm schon näher. Jetzt steht unser Text zwischen >>> <<<

Mit Quantifiern lassen sich Teilausdrücke wiederholen. Dabei Unterscheidet man zwischen 2 Arten von Quantifiern. Zum einen die gierigen, die so viele Zeichen wie möglich schlucken wollen.
Und zum anderen die weniger Gierigen. Der Unterschied zwischen diesen Beiden Versionen, ist das an der Nicht-Gierigen-Version am Ende ein ? - Zeichen steht. Dazu wollen wir uns ein Beispiel ansehen. Zuerst die gierigen Quantifiern...

#!/usr/bin/perl -w

use strict;

my $secret = "MasterCard : 55543214543 ";
my @array=(0);
my $counter=0;

while($counter!=6){
  $array[$counter]=$secret;
  $counter++;
 }

$array[0] =~s/\d*/-/;       # *=={0,}
$array[1] =~s/\d+/-/;       #mindestens 1 Vorkommen
$array[2] =~s/\d?/-/;       #gleichwertig zu {0,1}
$array[3]=~s/\d{8}/-/;     #Exakt 8 Zahlen ersetzten
$array[4]=~s/\d{1,}/-/;    #wie schon \d* mindestens 1 Vorkommen
$array[5]=~s/\d{2,4}/-/#Mindestens 2 Vorkommen höchstens 4 Vorkommen


$counter=0;
foreach(@array){
  print "$array[$counter]" , "\n";
  $counter++;
 }


Folgende Ausgabe sollten sie nun erhalten....

-MasterCard : 55543214543
MasterCard : -
-MasterCard : 55543214543
MasterCard : -543
MasterCard : -
MasterCard : -3214543


Kommen wir nun zur Nichtgierigen Version der Quantifiern....

#!/usr/bin/perl -w

use strict;

my $secret = "MasterCard : 55543214543 ";
my @array=(0);
my $counter=0;

while($counter!=6){
   $array[$counter]=$secret;
   $counter++;
  }

$array[0] =~s/\d*?/-/;   # *=={0,}
$array[1] =~s/\d+?/-/#mindestens 1 Vorkommen
$array[2] =~s/\d??/-/;   #gleichwertig zu {0,1}
$array[3]=~s/\d{8}?/-/;   #Exakt 8 Zahlen ersetzten
$array[4]=~s/\d{1,}?/-/;   #wie schon \d* mindestens 1 Vorkommen
$array[5]=~s/\d{2,4}?/-/#Mindestens 2 Vorkommen höchstens 4 Vorkommen


$counter=0;
foreach(@array){
  print "$array[$counter]" , "\n";
  $counter++;
 }


Hier erhalten sie nun folgende Ausgabe.....

-MasterCard : 55543214543
MasterCard : -5543214543
-MasterCard : 55543214543
MasterCard : -543
MasterCard : -5543214543
MasterCard : -543214543


Am besten kann man die gierige Version von der Nichtgierigen in den Beispielen.....

#gierig
$array[4]=~s/\d{1,}/-/;  #wie schon \d* mindestens 1 Vorkommen
$array[5]=~s/\d{2,4}/-/;  #Mindestens 2 Vorkommen höchstens 4 Vorkommen
#nicht gierig
$array[4]=~s/\d{1,}?/-/;  #wie schon \d* mindestens 1 Vorkommen
$array[5]=~s/\d{2,4}?/-/;  #Mindestens 2 Vorkommen höchstens 4 Vorkommen


....unterscheiden. Die gierige Version nimmt das Wort "mindestens" genau und schluckt alle Zahlen, da wir ja keine Grenzen gesetzt haben. Stellt man dem ganzen ein Fragezeichen ? ans Ende, schon haben wir die Nichtgierige Version. Nun werden wirklich nur "mindestens" Zeichen verschluckt.

Um Teilausdrücke für spätere Verwendungen zu benutzen werden diese mit Hilfe von runden Klammern gespeichert. Beispiel...

#!/usr/bin/perl -w

use strict;

my $secret = "Alle guten Dinge der Welt findet man in der Programmiersprache Perl";
$_=$secret;

while(1){
  if(/\b\w{3}\b/g){
     print "Wort mit 3 Buchstaben gefunden\n";
    }
  else{last;}
}


Wir suchen alle Wörter die 3 mit 3 Buchstaben in unserer Variable $secret. Zwar bekommen wir jetzt 3 mal ausgegeben das ein Wort mit 3 Buchstaben gefunden wurde. Aber welche? Um dies herauszufinden müssen wir nur die Teilausdrücke die uns interessieren einklammern. Der Teilstring der dann gefunden wird wird in der Variable $1 gespeichert...

#!/usr/bin/perl -w

use strict;

my $secret = "Alle guten Dinge der Welt findet man in der Programmiersprache Perl";
$_=$secret;

while(1){
  if(/\b(\w{3})\b/g){
     print "Wort mit 3 Buchstaben gefunden : $1\n";
   }
  else{last;}
}


Nun steht nach jedem Schleifendurchlauf ein Wort mit 3 Buchstaben in der Variable $1. Was aber nun wenn man mehrer Wörter als Teilausdrücke speichern will. Dazu gibt es weitere Variablen : $1, $2, $3, $4...usw.
Wenn sie Beispielsweise aus dem Quelltext einer Webseite alle Links herauspicken wollen...

#!/usr/bin/perl -w

use strict;

my $links = q!Und <a href="http://www.pronix.de/index.html">hier</a>
          kommen sie zur Hauptseite<br>!;

$_=$links;

 if(/.*?(<a href="(.*?)">).*/){
   print "Der komplette Link lautet : $1\n";
   print "Das Ziel diese Links ist : $2 \n";
  }


Die Ausgabe des Textes lautet dann...

Der komplette Link lautet : <a href="http://www.pronix.de/index.html">
Das Ziel diese Links ist : http://www.pronix.de/index.html

An dem Beispiel.....

(/.*?(<a href="(.*?)">).*/)

...sehen sie auch das es möglich ist, in Klammern weitere Klammern zur Speicherung von Teilstrings zu verwenden. Langsam kann man schon erkennen das Reguläre Ausdrücke recht komplex werden können. Hier die Erklärung zu dem eben verwendeten...

  • .*? = Es können bieliebige Zeichen stehen, diese interesieren uns aber nicht (nicht gierig)
  • (<a href="(.*?)">) = wir speichern alle <a href="beliebiger Text"> in $1 und das Ziel (.*?) davon in $2
  • .* = die restlichen Zeichen interessieren uns nicht

Das soll nun ein kleiner Überblick über die Regulären Ausdrücke gewesen sein. Über dieses Thema lässt sich ein ganzes Buch verfassen. Ich hoffe Ihnen damit ein wenig Überblick über diese sehr Umfangreiche Thema verschafft zu haben.

ein Kapitel zurück          nach oben           ein Kapitel weiter


© 2001,2002 Jürgen Wolf