Forum: PC-Programmierung Fehler bei (Perl) RegEx


von Vlad T. (vlad_tepesch)


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.

von Sven P. (Gast)


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[^"]*?)"/;

von (prx) A. K. (prx)


Lesenswert?

Müsste so gehen:
1
$test =~ /.*h r e f="(.*?foo.*?)"/;

von Vlad T. (vlad_tepesch)


Lesenswert?

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

Sven P. schrieb:
> Ne, er nimmt den kleinsten, der mit href anfängt und mit foo aufhört,
> ohne was wegzuwerfen.


der kleinste wäre doch aber nur der Inhalt des 2.

von (prx) A. K. (prx)


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.

von Vlad T. (vlad_tepesch)


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.

von (prx) A. K. (prx)


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

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.