Sehr Umfangreiche Webseite zum Programmieren in C Perl CGI, Skripting, Konvertieren, int ceil sprintf hex oct floor Runden AbschneidenPerl Kurs Skripting Reguläre Ausdrücke Pattern Matching Operator String Matching Metazeichen Reguläre Ausdrücke Pattern Matching Operator String Matching Metazeichen Perl Kurs Kapitel 14

14.3. Ersetzen von Zeichenfolgen           zurück Ein Kapitel tiefer zum Inhaltsverzeichnis

Die zweite Möglichkeit zur Änderung für die Musterfindung, führt im Gegensatz zum Kapitel zuvor, einen einfachen Ersatz von Zeichenfolgen durch. . Hier der Syntax ...

$string =~ tr/SuchListe/ErsatzListe/;

Ein einfaches Beispiel: Sie wollen alle Buchstaben einer Textdatei die Sie als Kommandozeilenargument mit dem Programm gestartet haben, in Großbuchstaben umwandeln ...

#!/usr/bin/perl -w

use strict;

undef $/;
my $text=<>;

if($text =~ tr/a-z/A-Z/) {
         print $text , "\n";
        }

In diesem Beispiel wird jedes einzelne Zeichen von der Suchliste durch eines der Zeichen in ErsatzListe ersetzt.

Die Liste von Zeichen können Sie auch wörtlich schreiben ...

ABCDEF
A-F       #ABCDEF
A-CX-Z    #ABCXYZ
A-C0-9    #ABC0123456789

Hierzu noch ein paar Beispiele ...

#!/usr/bin/perl -w

$text = "Dieser Text soll für Transliterationen missbraucht werden";
print $text , "\n";

$text =~ tr/a-z/A-Z/;   #alles in Grossbuchstaben
print $text , "\n";

$_ = $text;
$anzahl_T = tr/T/T/;   #Anzahl von dem Buchstaben T in $text
print "In diesem Text kommen $anzahl_T \"T\" 's vor!\n";

$anzahl_Space = tr/ / /;    #Leerstellen in $text
print "In dem Text sind $anzahl_Space Leerstellen vorhanden\n";

An diesem Beispiel können Sie erkennen, dass tr/// im Skalaren Kontex (ohne ~) die Anzahl betroffener Zeichen zurückliefert. Vorrausgesetzt der Inhalt befindet sich in der Standartvariable $_.

Natürlich können Sie auch einzelne Zeichen löschen ...

#!/usr/bin/perl -w

$text = "Dieser Text soll für Transliterationen missbraucht werden";

$text =~ tr/enl/ /; #Buchstaben e n und l entfernen
print $text , "\n";

Was aber tun bei folgender Angabe ...

$text =~ tr/abcd/ABC/;

In diesem Fall werden alle Buchstaben abcd ersetzt duch ABC. Aus d wird nun aber auch ein C. Um dies zu vermeiden gibt es das Flag /d das nichtersetzbare Zeichen entfernt ...

$text =~ tr/abcd/ABC/d;

Weitere Flags und Ihre Bedeutung wären ...

Interessant dürfte es sein, den Text von Latin-1 in Unicode und wieder zurück zu konvertieren. Alle 255 darstellbaren Zeichen die es gibt können Sie so angegeben ...

\0-\xFF

Hier das Beispiel dazu ...

#!/usr/bin/perl -w

$text = "Ein häßlicher Text für Konvertierungen : üäöß";

$text =~ tr/\0-\xFF//CU;   #Latin1 -> Unicode
print $text , "\n";

$text =~ tr/\0-\x{FF}//UC;    #Unicode -> Latin1
print $text , "\n";

Wichtig ist es zu erwähnen, dass das Ersetzen mit tr/// schneller geht als mit s/// was für Internetanwendungen (CGI-Skripts) wichtig sein dürfte.

Nochmals eine kurze Zusammenfassung ...

14.4. Reguläre Ausdrücke - Vertiefung           zurück Ein Kapitel tiefer zum Inhaltsverzeichnis

Die Metazeichen haben Sie schon im ersten Kapitel der Regulären Ausdrücke kennen gelernt. Nun soll das Ganze noch ein wenig vertieft werden. Anfangen will ich mit dem Metazeichen und den 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, dass 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, dass 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 Sie dies ebenfalls am besten in eckigen Klammern ...

#!/usr/bin/perl -w

use strict;

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

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

print $text , "\n";

Ein Hinweis noch zum Backslashing wie ...

/\/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.

Als nächstes zum Zero-With-Assertion. Sogenannte Wortbegrenzter 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 Wortbegrenzter \b und Nicht-wortbegrenzter \B gearbeitet.

Nehmen Sie 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, dass durch die Flags /mg die Bedeutung von $ so verändert wurde das \n das Ende des Strings darstellt. Und ^ 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 Sie dem Programm schon näher. Jetzt steht der 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  ja keine Grenzen gesetzt wurden. Stellt man dem ganzen ein Fragezeichen ? ans Ende, schon haben Sie 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;}
}

Hier werden alle Wörter gesucht mit 3 Buchstaben in unserer Variable $secret. Zwar bekommen Sie jetzt 3 mal ausgegeben das ein Wort mit 3 Buchstaben gefunden wurde. Aber welche? Um dies herauszufinden müssen Sie die Teilausdrücke die Sie 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 herausziehen 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 ...

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 ...

Dies soll nun ein kleiner Überblick über die Regulären Ausdrücke gewesen sein. Ich hoffe Ihnen damit ein wenig Überblick über diese sehr Umfangreiche Thema verschafft zu haben.