Bio: Dynamisches Zusammenstellen von RegExps

Sup!

Ich habe ein kleines Problem. Ich habe ein Perl-Skript, welches eine Zeichenkette entgegennimmt. Es startet dann ein Programm, dass Quellcode von Webseiten zurueckliefert, in denen diese Zeichenkette vorkommt.

Dann soll das Programm noch Schnipsel aus dem Quellcode ausschneiden, in denen die Zeichenkette vorkommt.

Dazu macht das Programm vereinfacht ca. folgendes:

$wort = <STDIN>;
chomp($wort);
open IN,(".../programm $wort |");
... verschiedene Dinge passieren, schliesslich ist der Quelltext in $content;

while ($content =~ "m/<[Pp]>".$wort.".*?\n/s") {print $1;}

Letztere Zeile funktioniert aber irgendwie mal gar nicht, auch nicht vereinfacht... brauche ich ein eval oder sowas?

Gruesse,

Bio

  1. Hallo!

    Dazu macht das Programm vereinfacht ca. folgendes:

    $wort = <STDIN>;
    chomp($wort);
    open IN,(".../programm $wort |");
    ... verschiedene Dinge passieren, schliesslich ist der Quelltext in $content;

    while ($content =~ "m/<[Pp]>".$wort.".*?\n/s") {print $1;}

    Eigentlich sollte das so ähnlich funktionieren:

    my $wort = "hallo";

    while (<>) {
        if (/($wort/)) {
        Am Anfang von $_ steht $wort";
        }
    }

    Vermutlich müßte das dann wie folgt funktionieren:

    $content =~ "m/<[Pp]>($wort).*?\n/s"

    Aber wie Du sicher weißt bin ich keine PERL-Guru ;-)
    Aber das Beispiel aus meinem PERL-Buch hatte ich im Hinterkopf, vielleicht bringts ja was!

    Grüße
    Andreas

  2. Aloha!

    Dazu macht das Programm vereinfacht ca. folgendes:

    while ($content =~ "m/<[Pp]>".$wort.".*?\n/s") {print $1;}

    Letztere Zeile funktioniert aber irgendwie mal gar nicht, auch nicht vereinfacht... brauche ich ein eval oder sowas?

    Mein Perl-Tutorial sagt im Zusammenhang mit der RegEx-Option "o" (compile once), dass folgender RegEx korrekt ist:

    while ($content =~ m/<[Pp]>($wort).*?$/m) {print $1;}

    s (single line) würde ich nicht unbedingt wählen wollen, bzw. nicht allein wählen wollen, denn m (multiple line) ist viel schöner, um mit dem Zeilenende $ auch mitten im Text Zeilenumbrüche zu finden.

    Die Option o würde den RegEx nur beim ersten Mal kompilieren - die Variable $wort könnte sich danach ändern, ohne Wirkung zu zeigen. Erhöht die Performance, kann aber stören.

    - Sven Rautenberg

    1. Sup!

      while ($content =~ m/<[Pp]>($wort).*?$/m) {print $1;}

      s (single line) würde ich nicht unbedingt wählen wollen, bzw. nicht allein wählen wollen, denn m (multiple line) ist viel schöner, um mit dem Zeilenende $ auch mitten im Text Zeilenumbrüche zu finden.

      Die Option o würde den RegEx nur beim ersten Mal kompilieren - die Variable $wort könnte sich danach ändern, ohne Wirkung zu zeigen. Erhöht die Performance, kann aber stören.

      Hmm...mal testen. Erstmal vielen Dank... ich stoere sonst nachher weider ;-)

      Gruesse,

      Bio

      1. Aloha!

        Hmm...mal testen. Erstmal vielen Dank... ich stoere sonst nachher weider ;-)

        Du wirst möglicherweise die runden Klammern anders setzen wollen (wenn du weißt, was in $wort steht und das in $1 überträgst, um es auszudrucken - hm, ist irgendwie einfacher, gleich $wort zu drucken).

        In diesem Zusammenhang sei gesagt, dass im single-line-Modus der Punkt auch auf den Zeilenumbruch matcht. Deshalb ist dieser Modus nicht unbedingt das, was du willst - vor allem, da du non-greedy suchst.

        - Sven Rautenberg

        1. Sup!

          Nene, ich will ja alles in dem Paragraph, in dem auch das Wort steht, extrahieren... und es ist ja nicht gesagt, daß das Wort in der selben Zeile wie der paragraph steht und überhaupt, dieser Single-Multiline-Quark verwirrt mich... ich meine, es sind mehrere Zeilen in einer Variablen - brauche ich jetzt den single- oder multiline modus?

          Vielleicht eleminiere ich einfach alle \n und matche dann von <p> bis ausschliessend zum nächsten.

          Gruesse,

          Bio

          1. Aloha!

            Nene, ich will ja alles in dem Paragraph, in dem auch das Wort steht, extrahieren... und es ist ja nicht gesagt, daß das Wort in der selben Zeile wie der paragraph steht und überhaupt, dieser Single-Multiline-Quark verwirrt mich... ich meine, es sind mehrere Zeilen in einer Variablen - brauche ich jetzt den single- oder multiline modus?

            Du willst also folgendes Suchmuster suchen:

            <p>.....DASWORT.....</p>

            Wobei beliebig Zeilenumbrüche innerhalb des Musters vorkommen könnten.

            Dann ist in der Tat der Single-Line-Modus richtig. Und du suchst nach:
            /<[pP]>(.*?$wort.*?)</[pP]>/s
            und hast alles zwischen <p> und </p> danach in $1 (wegen der runden Klammer.

            Es sei an dieser Stelle angemerkt, dass du zum wirklich korrekten Verarbeiten von HTML einen Parser benötigst, keine regulären Ausdrücke. In HTML ist ja das End-Tag (leider) optional, du würdest beim fehlenden End-Tag also ein Problem kriegen und mehr finden, als du willst. Dem kann man auch nicht entgegentreten, denn irgendein festes Muster hinten muss sein. Hier eben <\p>. Sonst finden .*? nämlich weisungsgemäß Null Zeichen.

            - Sven Rautenberg