regex pattern und replace argumente in einer Funktion nutzen.

regex pattern und replace argumente in einer Funktion nutzen.

am 24.11.2007 17:40:45 von Gerhard Wolf

Hallo,

ich wollte mir gerade eine Funktion bauen mit 3 Argumenten
1: eine URL
2: ein Regulärer Ausdruck
3: ein replace Argument
um eine substitution in eine Funktion zu packen.

Das klappt aber nicht wie gewünscht. In dem Beispiel sollte
23.11.07 17:59 - 0,596
ausgegeben werden. Im Subst (in der Funktion) habe ich verschiedene
Varianten mit '\'.... ausporbiert ohne Erfolg.

------------------------------------------------------------ ---------------------
#!/usr/bin/perl
use LWP::Simple;

&getHTMLContent('http://www.benzinpreis.de','.+Rohö.+te xtfont>(\d+\
\d+\.\d+ \d+:\d+).+?(\d+\,\d+).+','$1 - $2');


sub getHTMLContent {
my $content = get $_[0];
$content =~ s/$_[1]/$_[2]/ms;
print $content;
}

Re: regex pattern und replace argumente in einer Funktion nutzen.

am 25.11.2007 19:31:40 von sheinrich

Hallo Gerhard,

On Nov 24, 5:40 pm, Gerhard Wolf wrote:
> Hallo,
>
> ich wollte mir gerade eine Funktion bauen mit 3 Argumenten
> 1: eine URL
> 2: ein Regulärer Ausdruck
> 3: ein replace Argument
> um eine substitution in eine Funktion zu packen.
>
> Das klappt aber nicht wie gewünscht. In dem Beispiel sollte
> 23.11.07 17:59 - 0,596
> ausgegeben werden. Im Subst (in der Funktion) habe ich verschiedene
> Varianten mit '\'.... ausporbiert ohne Erfolg.
Du moechtest also eine formatierte Ausgabe unter Verwendung einzelner
Teilstrings aus der HTML-Seite erreichen.
Eine Substitution ist dafuer nicht notwendig, da du die HTML-Seite
nicht weiterverwenden willst.
Es reicht ein einfaches Patternmatching.

>
> ------------------------------------------------------------ --------------=
-------
> #!/usr/bin/perl
> use LWP::Simple;
>
> &getHTMLContent('http://www.benzinpreis.de','.+Rohö.+textf ont>(\d+\
> \d+\.\d+ \d+:\d+).+?(\d+\,\d+).+','$1 - $2');
Dein Pattern enthaelt Fehler.
Die Umlaute sind in der Quelle durch Entities kodiert. Du musst sie
also auch im Pattern verwenden.
Es fehlt der erste feste Punkt im Datum (vielleicht Cut & Paste?).
Es ist auch unnoetig kompliziert aufgebaut.

>
> sub getHTMLContent {
> my $content =3D get $_[0];
> $content =3D~ s/$_[1]/$_[2]/ms;
Du verwendest die Modifier m (multiline) und s (single line), die sich
widersprechen und hier auch nicht gebraucht werden, da du keinen der
Zeilenanker ^ oder $ benutzt.

> print $content;
Du willst die formatierten Matches, nicht den HTML-Content.

> }

Ich schlage die Verwendung der Funktionen printf oder sprintf vor.
Nachteil: Die Argumente werden in derselben Reihenfolge der Matches
eingebaut.
Hier funktioniert das, aber ich weiss nicht, was du mit der Sub sonst
noch vorhast ;-)
Du muesstest entweder in deiner Routine die Reihenfolge umbauen oder
nacheinander mehrere Matches vornehmen.
Es gibt auch eine Syntax nach der man im printf-Format angegeben kann,
den wievielten Parameter die Schablone benutzen soll, aber ich habe
sie noch nie in Perl verwendet. (man printf nachschauen)

#!/usr/bin/perl
use LWP::Simple;

getHTMLContent('http://www.benzinpreis.de',
'Rohölpreis.+textfont>([\d.]+ [\d:]+).+?([\d,]
+)',
'%s - %s');

sub getHTMLContent {
my $content =3D get $_[0];

if (my (@matches) =3D ($content =3D~ /$_[1]/)) {
printf $_[2], @matches;
} else {
print "No Match\n";
}
}

Steffen

Re: regex pattern und replace argumente in einer Funktion nutzen.

am 25.11.2007 19:59:02 von Wolf Behrenhoff

sheinrich@my-deja.com schrieb:
>> $content =~ s/$_[1]/$_[2]/ms;
> Du verwendest die Modifier m (multiline) und s (single line), die sich
> widersprechen und hier auch nicht gebraucht werden, da du keinen der
> Zeilenanker ^ oder $ benutzt.

Die Modifier m und s widersprechen sich nicht.
m bewirkt, dass die Anker an jedem Zeilenanfang/ende des Teststrings
matchen und nicht nur am Anfang/Ende des Teststrings.
s bewirkt, dass . auch ein \n frisst.

Wenn ich das Originalposting schnell überfliege, sehe ich dort keine
Anker, also ist /m überflüssig. Da die REs jedoch übergeben werden
sollen, würde ich überhaupt keine Modifier in die Funktion schreiben,
sondern sie stattdessen direkt in der RE mit übergeben.

Also statt
m/test/i
m/(?i)test/
verwenden.

Wolf

Re: regex pattern und replace argumente in einer Funktion nutzen.

am 25.11.2007 21:18:28 von sheinrich

On Nov 25, 7:59 pm, Wolf Behrenhoff
wrote:
> sheinr...@my-deja.com schrieb:
>
> >> $content =3D~ s/$_[1]/$_[2]/ms;
> > Du verwendest die Modifier m (multiline) und s (single line), die sich
> > widersprechen und hier auch nicht gebraucht werden, da du keinen der
> > Zeilenanker ^ oder $ benutzt.
>
> Die Modifier m und s widersprechen sich nicht.
> m bewirkt, dass die Anker an jedem Zeilenanfang/ende des Teststrings
> matchen und nicht nur am Anfang/Ende des Teststrings.
> s bewirkt, dass . auch ein \n frisst.
Voellig richtig.
Ich hatte mich so erinnert, dass die Anker bei /s nur einmal am
Anfang, bzw. Ende des Strings matchen.
Aber das Verhalten ist einfach der Default und /s hat mit den Ankern
tatsaechlich nichts zu tun.

>
> Wenn ich das Originalposting schnell überfliege, sehe ich dort keine
> Anker, also ist /m überflüssig. Da die REs jedoch übergeben werden
> sollen, würde ich überhaupt keine Modifier in die Funktion schreiben,
> sondern sie stattdessen direkt in der RE mit übergeben.
>
> Also statt
> m/test/i
> m/(?i)test/
> verwenden.
Guter Vorschlag. Im Beispiel also
'(?s)Rohölpreis.+textfont>([\d.]+ [\d:]+).+?([\d,]
+)'
In der HTML-Quelle ist zwar kein Newline zwischen den Musterteilen,
aber das koennte sich ja aendern.

>
> Wolf

Steffen