Linux


Es gibt in dieser Welt so einige Dinge, um die man am liebsten einen großen Bogen machen möchte: den Gang zur Zulassungsstelle, den fälligen Zahnarztbesuch oder aber auch um ”reguläre Ausdrücke“.  Das Dumme ist nur, man macht sich als Programmierer das Leben unnötig schwer, wenn man darauf verzichtet!

Anhand einiger kleiner Beispiele, versuche ich mal die Arbeitserleichterung “reguläre Ausdrücke” näher zu bringen. Und wenn schon denn schon, sind alle Beispiele in Perl, sollten aber auch in PHP oder einer Hochsprache wie Java nachvollziehbar sein.

 

Situation 1: Ich brauche Ortsnamen die mit “M” beginnen

Die Lösung sieht in Perl wie folgt aus:

#!/usr/bin/perl
use strict;

my @orte = (”Hannover”, “Muenchen”, “Mainz”, “Hamburg”, “Marburg”);
my $einOrt;

foreach $einOrt (@orte)
{
   if ($einOrt =~ m/^M/)
   {
      print $einOrt.”\n”
   }
}

Der Mustervergleich findet in der IF-Bedingung mit “$einOrt =~ m/^M/” statt. Die Erläuterung ist ziemlich simpel:

  • =~ leitet den Vergelich ein (Beachte: =~ vs. ==) 
  • m bedeutet, dass wir einen Mustervergleich vornehmen wollen
  • ^heißt soviel wie “am Anfang” und
  • M heißt “M” ;-)

Um die minimalen Unterschiede zu anderen Programmiersprachen aufzuzeigen, hier das obige Beispiel in PHP:

<?php
$orte = array(”Hannover”, “Muenchen”, “Mainz”, “Hamburg”, “Marburg”);

foreach ($orte as $einOrt)
{
   if (preg_match(’/^M/’, $einOrt))
   {
      echo “$einOrt<br/>”
   }
}
?>

Es wird die Funktion preg_match verwendet. Dadurch können wir auf eine Einleitung des Vergleich mit “m” verzichten.

 

Situation 2: Suchen und Ersetzen

Dummerweise müssen wir alle Ortsnamen die ein “burg” im Namen haben, mit einem “schloss” ersetzen:

#!/usr/bin/perl
use strict;

my @orte = (”Hannover”, “Muenchen”, “Mainz”, “Hamburg”, “Marburg”);
my $einOrt;

foreach $einOrt (@orte)
{
   if ($einOrt =~ s/burg/schloss/)
   {
      print $einOrt.”\n”
   }
}

Die IF-Bedingung sollte sich hier von selber erklären. “s” bedeutet “substitute” und leitet den Vorgang ein mit dem Suchbegriff “burg” und nachfolgend die Ersetzung “schloss”.
Dieser Vorgang wird nur beim ersten Vorkommen des gesuchten Begriff “burg” vorgenommen. Wenn in einer Zeile alle Vorkommen eines Suchbegriffs ersetzt werden sollen, benötigen wir am Ende des Ausdrucks noch den Modifier “g” (für global). Beispielsweise wollen wir alle “n’s” mit einem “m” ersetzen:

#!/usr/bin/perl
use strict;

my @orte = (”Hannover”, “Muenchen”, “Mainz”, “Hamburg”, “Marburg”);
my $einOrt;

foreach $einOrt (@orte)
{
   if ($einOrt =~ s/n/m/g)
   {
      print $einOrt.”\n”
   }
}

Hierbei wird immer zwischen Groß- und Kleinschreibung unterschieden. Falls diese Unterscheidung nicht stattfinden soll, müssen wir dem Modifier “g” noch den Modifier “i” (für “ignore case”) anhängen:

if ($einOrt =~ s/m/n/gi)

Falls wir jetzt mehrere Zeichen auf einmal ersetzen wollen, brauchen wir die eckigen Klammern []. Beispielsweise wollen wir alle Vokale in einem Satz streichen:

#!/usr/bin/perl
use strict;

my $zeile = “Hallo Leute es ist 09:15 Uhr. Ende”
# [aeiou] Alle Vokale werden mit “” ersetzt
if ($zeile =~ s/[aeiou]//gi)
{
   print $zeile.”\n”
}

Alles was in unserem Suchmuster innerhalb der eckigen Klammern steht, wird nun ersetzt und zwar mit nix ;-)

Das Ganze lässt sich sozusagen negieren. Heißt, alles wird gestrichen, außer die Vokale:

if ($zeile =~ s/[^aeiou]//gi)

Innerhalb der eckigen Klammern bedeutet ^nicht “am Anfang” sondern so viel wie NICHT.

Wir haben aber auch die Möglichkeit, in unserem Beispiel einen Bereich zu ersetzen. Wenn wir z.B. alle Zahlen von 0 bis 9 mit einem Unterstrich ersetzen wollen, müssen wir Folgendes schreiben:

if ($zeile =~ s/[0-9]/_/gi)

 

Situation 3: Komplizierte Mustererkennung

 

Als Situation sei gegeben, dass wir KFZ-Kennzeichen überprüfen müssen. Wir gehen davon aus, dass KFZ-Kennzeichen wie folgt aufgebaut sind:

  1. Zuerst kommen ein bis drei groß geschriebene Buchstaben von A bis Z
  2. Dann folgt ein Bindestrich
  3. Danach 0 bis 3 groß geschriebene Buchstaben von A bis Z und
  4. am Schluss ein bis 4 Zahlen von 0 bis 9

Die Kennzeichen sind beispielsweise in einer Textdatei kfz.txt:

H-GH456
F-MS2207
NOM-T242
H-ZU1
HH-ZU1
HH-ZU
HH-ZUZU1
HHHH-ZU1

Das Perl-Programm sieht wie folgt aus:

#!/usr/bin/perl
use strict;

open(DATEI, “<kfz.txt”);
my @zeilen = <DATEI>
close(DATEI);

my $zeile;

foreach $zeile (@zeilen)
{
   if ( $zeile =~ m/^[A-Z]{1,3}\-[A-Z]{0,3}[0-9]{1,4}/)
   {
      print “Gueltig: “.$zeile.”\n”
   }
   else
   {
      print “Ungueltig: “.$zeile.”\n”
   }
}

 

Situation 4: Komplizierte Mustererkennung und Speicherung in Variablen

 

Jetzt geht es ein wenig härter zur Sache, es wird kryptisch! Sollte uns aber nicht abhalten, diesen letzten Schritt der Einführung durchzustehen. Nehmen wir an, wir haben aus einer Datenbank diverse Links zu Webseiten und FTP-Ordnern bekommen. Es muss eine Möglichkeit geben, dieses für eine Website so aufzubereiten, daß die Verlinkung korrekt dargestellt wird. Wir benötigen also das Protokoll (http oder ftp), eine URL und einen Titel. Jeder Eintrag kommt wie folgt formatiert aus der Datenbank:

{link:http://de.selfhtml.org/{SELFHTML-Seiten}}

Die “Umwandlung” geschieht wie folgt:

#!/usr/bin/perl
use strict;

my $zeile = “{link:http://de.selfhtml.org/{SELFHTML-Seiten}}”

$zeile =~ m/^\{link:(.*):\/\/(.*)\{(.*)\}\}\s*$/;
print “\$1: $1\t\$2: $2\t\$3: $3\n”

Was geschieht hier?

  1. Es findet eine Mustererkennung statt : m
  2. Wir gehen an den Satzanfang und Suchen die Sequenz ab “{link:” die bis zum nächsten Vorkommen von “:/” geht. Die “\” sind die sogenannten Escape-Zeichen, die Sonderzeichen markieren! Die normalen Klammern “()” gruppieren alles was innerhalb von diesem Muster vorkommt “(.*)”. D.h. es steht uns später in der Variable “$1″ zur Verfügung
  3. Die nächste Sequenz geht ab dem Vorkommen von “://” -> “:\/\/” los. Beachte: Die “\” sind die sogenannten Escape-Zeichen, die Sonderzeichen markieren! Sie endet beim nächsten Vorkommen von “{”. Der Inhalt steht uns als “$2″ zur Verfügung
  4. Gleich direkt daran, wird alles bis zum Vorkommen von }} in die nächste Variable “$3″ gepackt -> “(.*)\}\}”
  5. “\s*$/” bedeutet, dass ab hier nur noch Leerzeichen (”\s*”) bis zum Zeilenende (”$”) folgen dürften oder halt sofort das Zeilenende.
    Leerzeichen bedeutet ‘ ‘, \n, \r oder \t

Die Ausgabe sieht wie folgt aus:

$1: http $2: de.selfhtml.org/ $3: SELFHTML-Seiten

 

Ich hoffe, dieser kleine Einstieg hat etwas geholfen. Freue mich wie immer über Kommentare, Kritik usw.. Zur Vertiefung sei das Buch Reguläre Ausdrücke. Praxislösungen für PHP, Perl, MySQL und JavaScript empfohlen!

Wer den Namen Perl hört, denkt meist an kryptische Verbiegungen ohne Ende. Perl an sich, ist eigentlich nicht so kryptisch und sollte sich jedem, der eine Programmiersprache beherrscht, äußerst schnell erschließen. Für diese Klientel habe ich dieses kurze Tutorial geschrieben.

Die Perl-Programme wurden allesamt unter Linux getestet, müssten aber unter jedem Betriebssystem laufen, für das ein Perl-Interpreter bereitgestellt wird.

 

Download: Perl in einer Stunde

 

Ich bitte um Kommentare, Kritik!

Nachdem ich gestern mal ein paar TV-Aufnahmen nach XVid konvertieren wollte, ärgerte ich mich mal wieder eine halbe Stunde über die Unzulänglichkeiten diverser Tools für Windows und ich erinnerte mich an Avidemux, was mir schon unter Debian gute Dienste geleistet hatte.
Überrascht fand ich ein Windows-Binary, dass aber irgendwie gar nicht funzte.
Eine Google Suche nach “Avidemux SuSE RPM” brachte mich schließlich auf packman.links2linux.de mit Avidemux RPM’s plus den benötigten Lib’s für die diversen Codecs. Die Installation inkl. aller Abhängigkeiten war tatsächlich innerhalb von 10 Minuten gegessen.