Tom: Reguläre Ausdrücke

Hello,

nun muss ich mich mal mit dem ekligsten beschäftigen, was ich kenne. Reguläre Ausdrücke ;-))

Aus einer tabellarischen Struktur muss ich die Daten grabben. Die Tabellen sind in jedem File gleich aufgebaut, sodass mir in den Sinn kam, dass ich nur die Tags zählen lassen müsste.

<tr ***> </tr> <td ***> <td>

Irgendwo zwischen dem xten <td ***>DATEN</td>  stehen ja die Daten.

Aber selbst dazu bin ich ja zu blöd :-(
Wie lege ich fest, dass sich ein Muster n mal wiederholen muss, bis zum gesuchten Ausdruck
Natürlich muss man auch an die Whitespaces denken, ging mir noch durch den Kopf...

Wäre nett, wenn mir jemand kurze Nachhilfe geben könnte. Bin irgendwie neben der Rolle heute.

Harzliche Grüße aus http://www.annerschbarrich.de

Tom

--
Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
Nur selber lernen macht schlau
  1. Hi,

    nun muss ich mich mal mit dem ekligsten beschäftigen, was ich kenne. Reguläre Ausdrücke ;-))

    etwas so wundervolles findest Du eklig? Tststs ;-)

    Aus einer tabellarischen Struktur

    Nur der Form halber, damit das nicht in Vergessenheit gerät: RegExp sind nur in der Lage, Muster zu erkennen, nicht Strukturen. Ja, bei Dir scheint es um ein Muster zu gehen.

    Wie lege ich fest, dass sich ein Muster n mal wiederholen muss, bis zum gesuchten Ausdruck

    Mit {anz}, einer Variante von {min, max}.

    Natürlich muss man auch an die Whitespaces denken,

    Teil des Musters.

    Wäre nett, wenn mir jemand kurze Nachhilfe geben könnte. Bin irgendwie neben der Rolle heute.

    man Wald | grep Bäume

    Cheatah

    --
    X-Self-Code: sh:( fo:} ch:~ rl:° br:> n4:& ie:% mo:) va:) de:] zu:) fl:{ ss:) ls:~ js:|
    X-Self-Code-Url: http://emmanuel.dammerer.at/selfcode.html
    X-Will-Answer-Email: No
    X-Please-Search-Archive-First: Absolutely Yes
  2. Hello,

    nun muss ich mich mal mit dem ekligsten beschäftigen, was ich kenne. Reguläre Ausdrücke ;-))

    Aus einer tabellarischen Struktur muss ich die Daten grabben. Die Tabellen sind in jedem File gleich aufgebaut, sodass mir in den Sinn kam, dass ich nur die Tags zählen lassen müsste.

    <tr ***> </tr> <td ***> <td>

    Irgendwo zwischen dem xten <td ***>DATEN</td>  stehen ja die Daten.

    Aber selbst dazu bin ich ja zu blöd :-(
    Wie lege ich fest, dass sich ein Muster n mal wiederholen muss, bis zum gesuchten Ausdruck
    Natürlich muss man auch an die Whitespaces denken, ging mir noch durch den Kopf...

    Wäre nett, wenn mir jemand kurze Nachhilfe geben könnte. Bin irgendwie neben der Rolle heute.

    Harzliche Grüße aus http://www.annerschbarrich.de

    Tom

    Hi Tom,

    Ich weiß nicht genau, ob ich deine Frage richtig verstanden habe, und bin im Moment auch nicht richtig in den reg. Ausdrücken drin, aber wie wär's z.B. damit:
    (<td ***>DATEN</td>){9,9}(<td ***>DATEN</td>)
    Das würde den Ausdruck <td ***>DATEN</td> erst mindestens/maximal 9-mal matchen und den 10. Treffer kannst du dann zum Weiterarbeiten benutzen (preg_match() kann ja ein Array mitgeliefert bekommen, in dem die Treffer stehen, die durch runde Klammer im Audruck stehen).

    Gruß
    Sigi

  3. Hello,

    Hi,

    also wenn die Seiten immer gleich aufgebaut sind, dann kannst du das File auch Zeilenweise durchgehen und in Zeile X,Y,Z die Zeichen A bis B rausschneiden.

    Wenn dem nicht so ist, dann kannst du auch HTML-Kommentare verwenden um den Suchort einzugrenzen, natürlich nur wenn du auf die Erstellung der Files Einfluss hast :)

    Ist jedenfalls einfacher als sich RegEx dafür zu basteln *g*

    mfg

    PHP_Dude

    1. Hello,

      also wenn die Seiten immer gleich aufgebaut sind, dann kannst du das File auch Zeilenweise durchgehen und in Zeile X,Y,Z die Zeichen A bis B rausschneiden.

      Die HTML-Struktur ist immer gleich
      Es stehen aber mal mehr und mal weniger Daten zwischen den Tags, manchmal auch gar keine.

      Wenn dem nicht so ist, dann kannst du auch HTML-Kommentare verwenden um den Suchort einzugrenzen, natürlich nur wenn du auf die Erstellung der Files Einfluss hast :)

      Ich bekomme die Files aber über eine Abfrage und haben keinen Einfluss auf die Gestaltung.

      Ist jedenfalls einfacher als sich RegEx dafür zu basteln *g*

      Das muss ich aber sowieso endlich verinnerlichen.

      Harzliche Grüße aus http://www.annerschbarrich.de

      Tom

      --
      Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
      Nur selber lernen macht schlau
  4. Hi,

    Irgendwo zwischen dem xten <td ***>DATEN</td>  stehen ja die Daten.

    Hast Du mal daran gedacht mit striptags die Tabelle zu entfernen, so dass nur die Daten uebrigbleiben?

    Gruesse, Joachim

    --
    Am Ende wird alles gut.
    1. Hello,

      Irgendwo zwischen dem xten <td ***>DATEN</td>  stehen ja die Daten.
      Hast Du mal daran gedacht mit striptags die Tabelle zu entfernen, so dass nur die Daten uebrigbleiben?

      Ja, als erstes natürlich.
      Damit würde ich aber die einzige Ordnung beseitigen, aufg die ich mich verlassen kann.

      Also, sinn der Übung ist es, n <td>-Tags mit beliebigen Attributen und falls notwendig (n-1) </td>-Tags zu zählen, dann den beliebigen Text (HTML-konform) zu grabben, der durch das nächste </td> abgeschlossen wird.

      $reg_ort = "/(<td[^>]{0,}>){3}(.*)<\/td>/";

      $found = preg_match($reg_ort,$page,$_treffer);

      Leider habe ich es noch nicht richtig verstanden, sodass mein $_treffer-Array leer bleibt.

      Harzliche Grüße aus http://www.annerschbarrich.de

      Tom

      --
      Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
      Nur selber lernen macht schlau
      1. Hi,

        $reg_ort = "/(<td[^>]{0,}>){3}(.*)<\/td>/";

        ^^^^^
        jetzt muss das erste Teilmuster 3x auftauchen...

        Moeglicherweise hilft Dir folgende Vorgehensweise:
        Zerschneide mit split den Table bei allen "</td>". Danach koenntest Du auf die Teilstrings  sowas anzuwenden:
        "/<td.*>([^<>]+)$/"
        in der Klammer sollten dann Deine Daten stehen

        Gruesse, Joachim

        --
        Am Ende wird alles gut.
        1. Hello,

          hatte mir zwischendurch noch dies ausgedacht:

          $_treffer = explode('</td>',$page);

          $_treffer2 = array();
          foreach($_treffer as $element)
          {
            $_treffer2[] = trim(substr(strrchr($element,'>'),1));
          }

          echo "<pre>\n";
          print_r($_treffer2);
          echo "</pre>\n";

          klappt aber auch nicht so toll, weil ja auch ganze tables in den <td ***> </td> stehen können oder eben <b> oder sonstwelche Tags.

          Harzliche Grüße aus http://www.annerschbarrich.de

          Tom

          --
          Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
          Nur selber lernen macht schlau
          1. Hello,

            Hi,

            und wenn du da dann striptags() drüberlässt, dann müssten die Inhalte und ein paar leere Arrays überbleiben.
            Ausser du willst die <table>'s und die <b>'s erhalten.

            mfg

            PHP_Dude

          2. Hi,

            klappt aber auch nicht so toll, weil ja auch ganze tables in den <td ***> </td> stehen können oder eben <b> oder sonstwelche Tags.

            "/<td.*>([^<>]+)$/"

            schau doch mal sowas:

            $str = "
            <table border="1">
            <tr>
                <td>
                    <table>
                    <tr>
                        <td>data <b>daten</b></td>
                    </tr>
                    <tr>
                        <td>data <p>data</p></td>
                    </tr>
                    </table>
                </td>
            </tr>
            </table>
            ";

            echo $str;

            $arr =  explode("</td>",$str);

            foreach($arr as $val) echo "Teilstring: " . htmlentities($val) . "<br>";

            foreach($arr as $val){
                $val =  strip_tags ($val,"<b><p>");
                if (trim($val)) echo "Daten: " . $val . "<br>";
            }

            Gruesse, Joachim

            --
            Am Ende wird alles gut.
            1. Hello,

              ich habe Deine Idee verfolgt und das Pferd im wesentlichen mittels exlode() und striptags() von hinten aufgezäumt und tatsächlich mit wenigen Zeilen relativen Erfolg gehabt. Der rest ließ sich dann für diesen Spezialfall relativ einfach durch einfache substr() und trim() erledigen.

              Wennich die 70 Seiten eingetippt hätte, oder mit Copy & Paste Seite für Seite Feld für Feld übertragen hätte, wäre ich wphl morgen Abend noch nicht fertig. So hat es ca. 2 Stunden gedauert und war pünktlich zur Besprechung fertig.

              Trotzdem würde ich es gerne nochmal mit RegExp wiederholen, um dann ein universelleres Tool daraus zu machen.

              Danke jedenfalls für die gute Anregung.

              Harzliche Grüße aus http://www.annerschbarrich.de

              Tom

              --
              Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
              Nur selber lernen macht schlau
  5. Hi Tom,

    Aus einer tabellarischen Struktur muss ich die Daten grabben. Die Tabellen sind in jedem File gleich aufgebaut, sodass mir in den Sinn kam, dass ich nur die Tags zählen lassen müsste.

    Also z.B. so:

    <table cellspacing="0" cellpadding="0">
      <tr class="zeile">
        <td>Name</td>
        <td>Wert</td>
        <td>Blabla</td>
      </tr>
      <tr class="zeile"
        <td>Noch ein Name ;-)</td>
        <td>Noch ein Wert...</td>
      </tr>
    </table>

    Im Prinzip jedes tr ein Datensatz, ja?

    Dann probiers doch mal so:

    // ========================================
    $regex = "/<tr[^>]*>[\w\W]*<\/tr>/U";
    $subregex = "/<td[^>]*>[\w\W]*<\/td>/U";

    $match = preg_match_all($regex, $var, $treffer);

    $daten = array();

    foreach($treffer[0] as $key => $value)
    {
      $submatch = preg_match_all($subregex, $value, $subtreffer);
      $daten[$key] = $subtreffer[0];
    }

    echo "<pre>";
    print_r($daten);
    echo "</pre>";
    // ========================================

    Dann sieht die Ausgabe so aus:

    Array
    (
        [0] => Array
            (
                [0] => Name
                [1] => Wert
                [2] => Blabla
            )
        [1] => Array
            (
                [0] => Noch ein Name ;-)
                [1] => Noch ein Wert...
            )
    )

    Du hast also alle "Datensätze" in einem Array in $daten.

    Hope it helps ;-)

    MfG, Dennis.

    PS: Weiß jemand, wie ich [\w\W] eleganter lösen kann? Ich will einfach nur alle Zeichen matchen, inklusive Zeilenumbruch, Punkt tuts also nicht, ein [^] geht auch nicht.

    --
    Mein SelfCode: ie:{ fl:{ br:^ va:) ls:< fo:) rl:( n4:& ss:) de:> js:( ch:{ sh:( mo:} zu:|
    Sinnvolles Zitieren: Man zitiert nur Teilsätze des Vorposters
    auf die man sich bezieht! Nicht einfach alles.
    1. Hallo Dennis,

      <tr class="zeile">
          <td>Name</td>
          <td>Wert</td>
          <td>Blabla</td>
        </tr>
        <tr class="zeile"
          <td>Noch ein Name ;-)</td>
          <td>Noch ein Wert...</td>
        </tr>

      In einer Tabelle müssen alle Zeilen gleich viele Spalten haben ...

      PS: Weiß jemand, wie ich [\w\W] eleganter lösen kann? Ich will einfach nur alle Zeichen matchen, inklusive Zeilenumbruch, Punkt tuts also nicht, ein [^] geht auch nicht.

      der Punkt sollte es in Verbindung mit dem Modifikator s tun.

      Grüße aus Nürnberg
      Tobias

      1. Hi Tobias,

        In einer Tabelle müssen alle Zeilen gleich viele Spalten haben ...

        Uups, hatte da nur zum Testen mal noch eine Spalte mehr rein geschrieben ;-)

        PS: Weiß jemand, wie ich [\w\W] eleganter lösen kann? Ich will einfach nur alle Zeichen matchen, inklusive Zeilenumbruch, Punkt tuts also nicht, ein [^] geht auch nicht.
        der Punkt sollte es in Verbindung mit dem Modifikator s tun.

        Ok, thx. Man kann diese Modifikators doch auch nur auf Subpattern anwenden, oder?

        MfG, Dennis.

        --
        Mein SelfCode: ie:{ fl:{ br:^ va:) ls:< fo:) rl:( n4:& ss:) de:> js:( ch:{ sh:( mo:} zu:|
        Meine Homepage: http://www.riehle-web.com
        Tutorial: http://tutorial.riehle-web.com
      2. Hello,

        In einer Tabelle müssen alle Zeilen gleich viele Spalten haben ...

        Die können aber auch über colspan="x" festgelegt werden und dann steht die Anzahl eben (teilweise) im Attribut. Das macht das Ganze eklig.

        Harzliche Grüße aus http://www.annerschbarrich.de

        Tom

        --
        Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
        Nur selber lernen macht schlau
    2. Hello,

      leider kein Erfolg.
      Durch die table in table funktioniert das noch nicht.
      Ich werde noch ein wenig lesen und grübeln müssen.
      Dabei erschien mir die Idee so einfach.

      Ich muss auch nicht alle auf einmal grabben, sondern kann wirklich jeden Datenwert mit einer eigenen RegExp holen. Das ist zwar teuer, aber ich habe die Seiten ja schon offline liegen und mein Testserver kann ruhig mal 2 Minuten rechnen.

      Harzliche Grüße aus http://www.annerschbarrich.de

      Tom

      --
      Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
      Nur selber lernen macht schlau
      1. Hi Tom,

        leider kein Erfolg.
        Durch die table in table funktioniert das noch nicht.
        Ich werde noch ein wenig lesen und grübeln müssen.
        Dabei erschien mir die Idee so einfach.

        Hm, es dürfte in der Tat schwierig sein, da man anhand eines bloßen </td> nicht das Ende erkennen kann - das </td> kann ja auch in der inneren Tabelle vorkommen.

        Allerdings bin ich gerade auf der von Tobias verlinkten Seite noch auch etwas gestoßen, wass sich ganz interessant anhört: Conditional Subpatterns

        Man müsste also irgendwie abprüfen, ob nach dem <td> => [^<] => <table[^>]> kommt, wenn ja, dann müsste man erst nach dem </table> (und dann </td>) suchen, sonst nach direkt nach dem </td>.

        Da wäre wohl noch ein bisschen Auseinandersetzung mit dem Thema notwendig ;-)

        Ich muss auch nicht alle auf einmal grabben, sondern kann wirklich jeden Datenwert mit einer eigenen RegExp holen. Das ist zwar teuer, aber ich habe die Seiten ja schon offline liegen und mein Testserver kann ruhig mal 2 Minuten rechnen.

        Das ist doch schon mal gut.

        MfG, Dennis.

        --
        Mein SelfCode: ie:{ fl:{ br:^ va:) ls:< fo:) rl:( n4:& ss:) de:> js:( ch:{ sh:( mo:} zu:|
        That's life - Es gibt im Leben[tm] keine Zurück-Taste. (Fabian Transchel)
        1. Hi Tom,

          Man müsste also irgendwie abprüfen, ob nach dem <td> => [^<] => <table[^>]> kommt, wenn ja, dann müsste man erst nach dem </table> (und dann </td>) suchen, sonst nach direkt nach dem </td>.

          Gut, das habe ich jetzt soweit hingekriegt, klappt glaube ich auch:

          $subregex = "/<td[^>]*>(?(?=[^<]*<table[^>]*)[^<]*<table[^>]*>[\w\W]*<\/table>[\w\W]*<\/td>|[\w\W]*<\/td>)/U";

          Doch nun ist ein neues Problem aufgetaucht: Durch das </tr> von der inneren Tabelle wird der erste RegEx rausgebracht, und da beiße ich mir nun gerade die Zähne dran aus :-(

          Erst hatte ich sowas in der Art (wollte einfach den subregex anpassen):
          $regex = "/<tr[^>]*>(?(?=[\w\W]*<td[^>]*>[^<]*<table[^>]*>*)[\w\W]*<\/table>[\w\W]*|[\w\W]*)<\/tr>/U";

          Das hat aber schon mal gar nicht geklappt, dann mein zweiter Versuch:
          $regex = "/<tr[^>]*>[\w\W]*(<table[^>]*>[\w\W]*<\/table>[\w\W]*)*[\w\W]*<\/tr>/U";

          Doch auch da bin ich mit dem Ungreedy ins Stecken gekommen....

          Vielleicht kann irgendeiner von euch an dieser Stelle weitermachen ;-)

          MfG, Dennis.

          --
          Mein SelfCode: ie:{ fl:{ br:^ va:) ls:< fo:) rl:( n4:& ss:) de:> js:( ch:{ sh:( mo:} zu:|
          Bedeutung meines SelfCodes
  6. <tr ***> </tr> <td ***> <td>

    Irgendwo zwischen dem xten <td ***>DATEN</td>  stehen ja die Daten.

    Mal eine ganz andere Idee: Wenn es sich bei diesen HTML-Dateien um wohlgeformtes XML handelt, ließe sich da doch bestimmt was mit XSL-Transformation machen. Wenn es Quirks-HTML ist, würde ich das PEAR-Package XML_HTMLSax3 vorher drauf anzusetzen probieren. In dem Paket gibt es auch ein Beispiel-Script HTMLtoXHTML.php