Andreas Korthaus: unperformanter regulärer Ausdruck

Hallo!

Ich wollte mich gerade nochmal an meine Self-Archiv Datenbank wagen, und bei der Gelegenheit wollte ich nochmal alles neu parsen, um an Stelle der einzelnen Threads einzelne Postings pro Datensatz in die DB zu schreiben. Naja, hierzu habe ich jetzt einen Regulären Ausdruck geschreieben, der auf meinem Computer über 10.000 Dateien mit über 100.000 Postings parsen muß. Da sollte das ganze schon etwas performanter sein. Ich habe das jetzt wie folgt gemacht:

/*Beispielhaftes Posting:

<h2 class="sh2"><a class="an" name="m138412">(JAVA) Signierte Applets - Systemauslastung</a></h2>  <p>Die folgende Nachricht zum Thema stammt von:  <b>Axel Richter</b>,  <img src="/src/xgmail.gif" width="15" height="10" border="0" alt="E-Mail" /> <a href="mailto:axel.richter@ragbildung.de"><b>axel.richter@ragbildung.de</b></a>,  01. Oktober 2002, 10:59 Uhr  </p>  <p><tt>
*/

$pattern = "/<h2.*?><a.*?name="m([0-9]+)">((.*?)) (.*?)</a></h2>.*?<b>(.*?)</b>.*?([0-9]{2}). (\w+) ([0-9]{4}), ([0-9]{2}):([0-9]{2}) Uhr(.*?)<tt>(.*?)</tt>/";

preg_match_all($pattern,$string,$matches,PREG_SET_ORDER);

Ihr kennt die Daten ggfs. etwas besser als ich, komme ich mit dem Ausdruck für das 2002er Archiv klar, oder bekomme ich irgendwo Probleme? Bei Tests hat es funktioniert, halt nur etwas langsam.  Ich verwende ja immer .*?, ist glaube ich nicht so toll, aber ich weiß nicht was ich an Stelle dessen schreiben soll!

Und nochwas, ein weiterer Punkt den ich optimieren könnte, ich öffen die Dateien wie folgt:

$data = file($file);
$string = implode("",$data);

Das war mal eben das einfachste, oder sollte ich unter Performance-Gesichtspunkten eher fopen() bevorzugen?

Viele Grüße
andreas

  1. Hallo!

    Also nachdem das von der Performance her nicht ganz so wild war(komplettes 2002er Archiv parsen dauert keine 10 Minuten) habe ich ein anderes Problem: es fallen viele Postings unter den Tisch.  Von ca. 140.000 Postings kommen nur 110.000 in der Datenbank an. Das liegt am regulären Ausdruck, nur woran genau? Wie könnte ich das testen? Mein Ausdruck sieht jetzt so aus:

    /<h2.*?><a.*?name="m([0-9]+)">((.*?)) (.*?)</a></h2>.*?<b>(.*?)</b>.*?(<b>(.*?)</b>.*?)?([0-9]{2}). ([\w&; ]+) ([0-9]{4}), ([0-9]{2}):([0-9]{2}) Uhr(.*?)<tt>(.*?)</tt>/

    /*Beispielhaftes Posting:

    <h2 class="sh2"><a class="an" name="m138412">(JAVA) Signierte Applets - Systemauslastung</a></h2>  <p>Die folgende Nachricht zum Thema stammt von:  <b>Axel Richter</b>,  <img src="/src/xgmail.gif" width="15" height="10" border="0" alt="E-Mail" /> <a href="mailto:axel.richter@ragbildung.de"><b>axel.richter@ragbildung.de</b></a>,  01. Oktober 2002, 10:59 Uhr  </p>  <p><tt>
    */

    Ich habe z.B. gemerkt, das beim Datum zw. Monat und Jahr manchmal auch 2 Leerzeichen liegen. Vermutlich habe ich mehrere solcher Probleme. Wie könnte ich den oberen Ausdruck optimieren, um
    a) alle Postings zu erfassen, und
    b) die Performance zu steigern(Interesse halber)?

    Viele Grüße
    Andreas

    PS: Wußte gar nicht das es Posting-IDs doppelt geben kann! Dadurch habe ich jetzt keinen Primary-Key mehr!

  2. Hi!

    Ich weiss zwar nicht (und kann's momentan auch nicht ausprobieren) ob .*? langsamer ist als [^x]* aber alternativ zu deinen .*? kannst du ja auch nach dem nicht-Vorkommen eines bestimmten Zeichens abfragen:

    statt:
    <h2.*?><a.*?name="m([0-9]+)">((.*?))...etc..
    <h2[^>]*><a[^>]+name="m([0-9]+)">(([^)]*))...etc..

    mfG
    brand

    1. Hi!

      Ich weiss zwar nicht (und kann's momentan auch nicht ausprobieren) ob .*? langsamer ist als [^x]* aber alternativ zu deinen .*? kannst du ja auch nach dem nicht-Vorkommen eines bestimmten Zeichens abfragen:

      statt:
      <h2.*?><a.*?name="m([0-9]+)">((.*?))...etc..
      <h2[^>]*><a[^>]+name="m([0-9]+)">(([^)]*))...etc..

      Gute Idee, leider geht das meist nicht, da das ausgeschlossene Zeichen ja im String vorkommen kann, aber manchmal gehts.

      Jetzt habe ich es so probiert:
      $pattern = "/<h2[^>]+>\s*<a.*?name="m([0-9]+)">\s*(([^)]*)) *(.*?)</a>.*?<b>(.*?)</b>.*?(href="mailto:([^"]+)">.*?)?([0-9]{2}).\s*([\w&; ]+)\s*([0-9]{4}),\s*([0-9]{2}):([0-9]{2}).*?<tt>(.*?)</tt>/";
      /*
      <h2 class="sh2"><a class="an" name="m138412">(JAVA) Signierte Applets - Systemauslastung</a></h2>  <p>Die folgende Nachricht zum Thema stammt von:  <b>Axel Richter</b>,  <img src="/src/xgmail.gif" width="15" height="10" border="0" alt="E-Mail" /> <a href="mailto:axel.richter@ragbildung.de"><b>axel.richter@ragbildung.de</b></a>,  01. Oktober 2002, 10:59 Uhr  </p>  <p><tt>
      */

      So, jetzt finde ich schon erheblich mehr, jetzt fehlen mir von 140.000 Postings noch etwas über 1000. Jemand ne Idee wo ich vielleicht noch etwas allgemeiner sein könnte?

      Viele Grüße
      Andreas