Fehler bei (Perl) RegEx

#2258467
Lesenswert?

Hi, ich hoffe von euch kann mir jemand einen Tip geben:

Ich habe folgendes Script
1
my $test = '[/li][li][a   h r e f="abcd.htm" title="abcd"]abcd[/a] - [a   h r e f="defg%28foo%29" title="Rdefg"]defg[/a] - 05:11';
2

3
$test =~ /h r e f="(.*?foo.*?)"/;
4
print $1 ."\n";

Ich möchte nur den ref bekommen, der das foo enthält und obwohl ich die 
die Fragezeichen hinter den Sternen benutze matcht er den größten 
möglichen String, anstatt den kleinsten.

ausgegeben wird
1
abcd.htm" title="abcd"]abcd[/a] - [a   h r e f="defg%28foo%29
anstatt
1
defg%28foo%29

Wär für einen Hinweis dankbar
Vlad

edit:
Man ist das ansterengend hier html-code in den Beitrag zu bekommen, 
nichtmal in den Codetags wird das toleriert.
Gast #2258481
Lesenswert?

Vlad Tepesch schrieb:
> Ich möchte nur den ref bekommen, der das foo enthält und obwohl ich die
> die Fragezeichen hinter den Sternen benutze matcht er den größten
> möglichen String, anstatt den kleinsten.
Ne, er nimmt den kleinsten, der mit href anfängt und mit foo aufhört, 
ohne was wegzuwerfen.

Verbiete ihm mal, über Anführungszeichen hinwegzusuchen:
1
$test =~ /h r e f="([^"]*?foo[^"]*?)"/;
#2258495
Lesenswert?

Vlad Tepesch schrieb:

> Danke. funktioniert beides, wobei mir immer noch nicht klar ist, warum
> meins nicht funktioniert.

Weil in deinem String zweimal "h r e f" drin steht und Perl keinen Grund 
sieht, dem ersten zu misstrauen, wo doch was passendes rauskommt. Ganz 
so global werden deine "shortest match" Fragezeichen nämlich nicht 
verstanden. Die beziehen sich nur auf das "*" unmittelbar davor, nicht 
auf alle phantastilliarden Möglichkeiten der gesamten RegEx.

Das läuft immer noch von links nach rechts ab und wenn das "h r e f" 
Pattern schonmal passt und der Rest dann auch noch, dann ist der Karton 
zu.

Das ist ja der Trick an meiner Version. Das ".*" vorneweg frisst per 
longest match den falschen "h r e f" weg, so dass nur der letzte solche 
vor dem "foo" erwischt wird.
#2258513
Lesenswert?

A. K. schrieb:
> Das ist ja der Trick an meiner Version. Das ".*" vorneweg frisst per
> longest match den falschen "h r e f" weg, so dass nur der letzte solche
> vor dem "foo" erwischt wird.

nur das im Falle eines replace-regex auch Teile getroffen werden, die 
nicht ersetzt werden sollten. Da ist die erste version besser.

Dennoch ein dickes Danke für die Erklärung.
#2258519
Lesenswert?

Vlad Tepesch schrieb:

> nur das im Falle eines replace-regex auch Teile getroffen werden, die
> nicht ersetzt werden sollten. Da ist die erste version besser.

Das ist das Fiese an Programmierung. Der Rechner tut immer nur genau das 
was man ihm sagt. Nicht zwangsläufig das, was man von ihm will. Dein 
"besser" lässt ihn völlig kalt.

Es kann beim Verständnis übrigens helfen, wenn man sich den Ablauf der 
Verabeitung einer RegEx in Form eines endlichen Automaten vorstellt. 
Soll keiner sagen, ein Informatikstudium brächte nix für die Praxis. ;-)

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren