Gier

am Beispiel der Regierung von Hessen-Darmstadt

Im "Hessischen Landboten" beschäftigt sich Georg Büchner mit der Steuereintreibung im Großherzogtum Hessen und den Verwendungszwecken des Geldes.

Eine rhetorische Figur ist die Einleitung eines jeden Absatzes mit derselben Redewendung. "Für Verwendungszweck Betrag Gulden." Manchmal wird "Gulden" auch mit "fl." abgekürzt.

Diesen Text kann man durch

perl -p -i -e 's/(Für.*)(fl|Gulden)\./$1Euro./' landbote.txt
aktualisieren.

Wie sucht Perl nun nach dieser Textstelle? Antwort: gierig!

Pacman verschlingt jeden Text, auf den
'Für.*' passt, bis zum Ende der Zeile.

Nun sieht er sich am Ende der Zeile nach
dem ersten Zeichen von <fl> oder <Gulden> um,
findet's aber nicht.

Also speit er das letzte der vorher
verschlungenen Zeichen aus und sieht nach, ob <f> oder
<G> auf es passt.

Passt immer noch nicht, also weiter.

Nachdem er die ganze Kette
<Gulden.> wieder ausgespuckt hat, stellt er voll Freude
fest, dass das zu suchende Muster darauf passt.

Problem bei der obigen Angabe: Man hängt an der Bedingung, dass in derselben Zeile tatsächlich nur einmal hinter "Für" "Gulden." oder "fl." kommt! Wenn diese Ausdrücke mehrmals vorkommen, wählt der Pacman immer den maximal möglichen String, der von der ersten Suchposition aus gefunden wird (leftmost longest).

Daher als allgemeine Regel: Baue spezifische Suchmuster ein! Besonders ungeeignet: .*

Besser: Ermögliche das Auffinden nur innerhalb desselben Satzes. Möglichkeit:

perl -p -i -e 's/(Für[^!?.:;]*)(fl|Gulden)\./$1Euro./' landbote.txt

Praktischere Anwendung

Finde Tags in HTML-Dokument. Ein Tag kann gefunden werden durch:
#!/usr/bin/perl -w

while(<>) {
    my @matches = ($_ =~  m/(<[^>]*>)/g);
    foreach $tag(@matches) {
	print $tag, "\n";
    }
}
Was nicht klappt, ist ein Matching in der Form von /<b>[^</b>]*</b>/ . Hier muss man sich anders behelfen.

Lehre Perl Bescheidenheit!

Durch Anfügen eines Fragezeichens an Quantifizierer wird Perl gezwungen, den kürzestmöglichen Treffer zu verwenden.
#!/usr/bin/perl -w

while(<>) {
    my @matches = (m{<(\w+).*?>.*?}g);
    foreach $tag(@matches) {
	print $tag, ":\t", $_;
    }
}
In diesem Skript wird jedes gepaarte Tag erkannt und angezeigt.

Die "Bescheidenheits-Option" ist ein Merkmal von Perl gegenüber anderen Programmen und Sprachen mit Verarbeitung regulärer Ausdrücke! Sie sollte aber nur dort eingesetzt werden, wo keine andere Möglichkeit zupaß kommt. Besser im Sinne der Effizienz ist, durch spezifischere Muster Mißverständnisse zu vermeiden.


Zurück Weiter
Johannes Hüsing