Bio: RegExp's zur Laufzeit erstellen

Sup!

Ich hab'n Problem. Und zwar: Ein CGI nimmt eine Reihe von Suchwoertern entgegen. Es startet eine Suchmaschine, die gibt URLs zurueck. Das CGI liest den Quellcode der Seiten in jeweils ein Skalar ein. Fuer jeden Quelltext soll das CGI alle Abschnitte von <p> bis zum naechsten <p> finden (die Paragraphs werden leider nicht geschlossen...), in denen mindestens ein Suchwort vorkommt... also quasi Quelltextskalar =~
m/<p>(.*?(?:suchwort|suchwort|suchwort).*?\n)(?:</html><p>)/s

Das dumme ist nur, dass es nicht trivial ist, zur Laufzeit einen Regexp zu erstellen, mit Modifier etc. pp. - man kann ja nicht einfach aus double-quoted oder single-quoted strings einen RegExp machen, die Dinger haben ja eigentlich ganz eigene Quotes, hinter denen dann noch die modifier kommen, und eine string-to-regexp funktion habe ich noch nicht gefunden.

Wie also geht das?

Gruesse,

Bio

  1. use Mosche;

    Ich hab'n Problem. Und zwar: Ein CGI nimmt eine Reihe von Suchwoertern entgegen. Es startet eine Suchmaschine, die gibt URLs zurueck. Das CGI liest den Quellcode der Seiten in jeweils ein Skalar ein. Fuer jeden Quelltext soll das CGI alle Abschnitte von <p> bis zum naechsten <p> finden (die Paragraphs werden leider nicht geschlossen...), in denen mindestens ein Suchwort vorkommt

    Also entweder habe ich dein Problem nicht verstanden, oder dir hilft vielleicht dieses Stückscher Testquellcode:

    ############### biotest ###########

    #!/usr/bin/perl -w
    use strict;
    use Data::Dumper;
    my %data = (
      'http://192.168.2.1' => '<html><head><title></title></body><p>dies ist ein langer text<p>und noch ein text suchwort1<p>und ein weiterer text (inzwischen schon der dritte) suchwort2<p></body></html>',
      'http://192.168.2.2' => '<html><head><title></title></body><p>dies ist ein langer <p>ein text suchwort1<p>und ein weiterer text (inzwischen schon der dritte)<p></body></html>',
      'http://192.168.2.3' => '<html><head><title></title></body><p>dies ist ein text<p>und ein text <p>und ein weiterer text (inzwischen schon der dritte) suchwort2<p></body></html>'
      );
    my @searchwords = qw(suchwort suchwort1 suchwort2);
    my %q;
    while (my ($url, $val) = each %data) {
      while($val =~ s/<p>(.*?)<p>/<p>/) {
        push (@{$q{$url}},$1) if (grep { $1 =~ /$_/ } @searchwords;
      }
    }
    print Dumper (%q);

    ############### / biotest ###########

    Der Unterschied zu deinem Ansatz ist derjenige, dass ich den Dateiinhalt nur Schritt für Schritt ansehe (mit dem s///) und auch nur jedes einzelne Suchwort einzeln abfrage (weil ich nicht wusste, wie ich aus dem Array den Regex bastel - so ist das zwar insgesamt weniger performant, aber nicht weiter schlimm, solange die Anzahl der Suchworte relativ gering ist).

    use Tschoe qw(Matti);

    PS: CGI ist eine Schnittstelle und kein Programm... *SCNR*

    1. use Mosche;

      Zum Glück wird der Valli nie dieses Stück Quellcode sehen :-)

      '<html><head><title></title></body><p>dies ist ein langer text<p>und noch ein text suchwort1<p>und ein weiterer text (inzwischen schon der dritte) suchwort2<p></body></html>',

      Mir ist noch eine performanzkritische Verbesserung eingefallen.

      push (@{$q{$url}},$1) if (grep { $1 =~ /$_/ } @searchwords;

      Du nimmst die Regex in grep {} raus und setzt statt dessen:

      push @{$q{$url}},$1 if grep { index($1,$_)+1 } @searchwords;

      Das sollte ein bißchen schneller laufen, geht aber nur, wenn du nicht irgenwelche Modifier reinbauen willst.

      use Tschoe qw(Matti);

  2. Sup!

    Moin!

    Das dumme ist nur, dass es nicht trivial ist, zur Laufzeit einen Regexp zu erstellen, mit Modifier etc. pp. - man kann ja nicht einfach aus double-quoted oder single-quoted strings einen RegExp machen, die Dinger haben ja eigentlich ganz eigene Quotes, hinter denen dann noch die modifier kommen, und eine string-to-regexp funktion habe ich noch nicht gefunden.

    Wie also geht das?

    Geht viel einfacher als du denkst: Einfach einen String in eine Variable stecken und diese im Regexp benutzen. (/blar${xyz}blubb/)

    Falls du Suchwörter vom User entgegen nimmst musst du diese natürlich escapen. Das geht wunderbar einfach mit quotemeta().

    Und da du mehrere Suchwörter hast und diese alle in einen String einbauen willst join()st du sie am besten noch mit einem | als Trennzeichen. :)

    Gruesse,

    Bio

    Gruß zurück,
    flgr

  3. Hallo,

    [...]

    perldoc -f quotemeta

    Gruesse,
     CK