Gerhard: Regular Expressions Wert der Wildcard ermitteln

Hallo,

ich bin auf der Suche nach einer Möglichkeit, in einem Suchtext ALLE Vorkommen des Suchmusters zu finden, und zwar nicht das Muster selbst, sondern den Wert einer Wildcard IM Muster. Da das vielleicht etwas kompliziert formuliert ist, hier mein konkretes Beispiel.

Der Text ist gewöhnlicher XHTML-Code. Unter anderem können dort auch Bilder vorkommen. Die Bilder die ich finden möchte, wurden von mir speziell mit Hilfe des id-Attributs des img-Tags gekennzeichnet. Der Einfachheit halber kommt das id-Attribut immer als erstes Attribut und immer genau 1 Leerzeichen nach dem öffnenden <img> Tag. Der Wert des id-Attributs beginnt immer mit der Zeichenkette "db" und enthält dann eine beliebig-stellige Zahl.

Also zum Beispiel:
blablabla... blablabla irgendwelche tags ... <img id="db1234" ..... /> blablabla ... blablabla <img id="db78" src="..." .... /> .. blablabla

Ich bin leider nicht so bewandert auf dem Gebiet der regulären Ausdrücke, aber ich weiß dass in manchen Texteditoren die Möglichkeit besteht (ich glaube mittels des $-Zeichens), eine Wildcard-Variable zu definieren, die dann weiterverwendet wird. In jedem Fall möchte ich am Schluss eine Liste aller IDs ohne das vorangestellte "db" haben, also in diesem Beispiel {1234,78}.

Optimal wäre eine Funktion, die den Suchtext entgegennimmt, ein Pattern der Form "<img id="db%MYWILDCARD%", und als Ergebnis ein Array von gefundenen Wildcard-Werten zurückliefert.

Wie der Name schon sagt, möchte ich das ganze mittels PHP automatisieren. Geht sowas überhaupt mit den PHP-eigenen Regex-Funktionen?

Danke und lG,
Gerhard

  1. Ich denke, du suchst einen xml-Parser.

    mfg Beat

    --
    ><o(((°>           ><o(((°>
       <°)))o><                     ><o(((°>o
    Der Valigator leibt diese Fische
    1. Ich denke, du suchst einen xml-Parser.

      Hm ich hoffe eigentlich da drum herum zu kommen. Wegen einer "so kleinen" Anforderung möchte ich nicht gleich auf XML-Parsing zurückgreifen müssen. Außerdem ist mein zu durchsuchender Text nicht zwingend wohlgeformt, d.h. Parser hätten damit wohl keine so große Freude...

      1. Ich denke, du suchst einen xml-Parser.
        Hm ich hoffe eigentlich da drum herum zu kommen.

        Warum?

        Wegen einer "so kleinen" Anforderung

        Nach kurzem überlegen wirst du feststellen, dass es äußerst komplex ist einige einfache Verarbeitungsregeln von XML in einen PCRE zu fassen.

        Außerdem ist mein zu durchsuchender Text nicht zwingend wohlgeformt, d.h. Parser hätten damit wohl keine so große Freude...

        Dann ist es kein XHTML sondern Codemüll. Keine Große freude ist dann untertrieben: wenn der Code nicht wohlgeformt ist, wird sich der Paser weigern.

        Es gibt aber auch parser, die Codemüll halbwegs ordentlich interpretieren: http://simplehtmldom.sourceforge.net/

      2. Ich denke, du suchst einen xml-Parser.
        Hm ich hoffe eigentlich da drum herum zu kommen. Wegen einer "so kleinen" Anforderung möchte ich nicht gleich auf XML-Parsing zurückgreifen müssen. Außerdem ist mein zu durchsuchender Text nicht zwingend wohlgeformt, d.h. Parser hätten damit wohl keine so große Freude...

        Handelt es sich bei deinem Anliegen um eine einmalige Transformation von Code? Dann kannst du mit einer Regex deine Wüste umbauen.

        Handelt es sich aber um reguläre häufige Prozeduren, dann wärst du besser bedient, nicht den Ausgabetext zu modifizieren, sondern die Quelldaten, bevor sie in den Ausgabetext gebaut werden.

        mfg Beat

        --
        ><o(((°>           ><o(((°>
           <°)))o><                     ><o(((°>o
        Der Valigator leibt diese Fische
  2. ich bin auf der Suche nach einer Möglichkeit, in einem Suchtext ALLE Vorkommen des Suchmusters zu finden, und zwar nicht das Muster selbst, sondern den Wert einer Wildcard IM Muster. Da das vielleicht etwas kompliziert formuliert ist, hier mein konkretes Beispiel.

    Setze dich mit den Stichworten "Subpattern" und "Non-capturing parentheses" auseinander.

    Der Text ist gewöhnlicher XHTML-Code.

    Wie du selbst schon sagst, ist er das nicht :p

    Geht sowas überhaupt mit den PHP-eigenen Regex-Funktionen?

    preg_match_all() ist hier dein Freund - es ist keine große Hexerei.

    Finde wörtlich <img id="db gefolgt von einer oder mehreren Dezimalzahlen die du speichern willst. That's it.

    1. preg_match_all() ist hier dein Freund - es ist keine große Hexerei.

      Finde wörtlich <img id="db gefolgt von einer oder mehreren Dezimalzahlen die du speichern willst. That's it.

      Das ist es wirklich. Danke für den Tipp. Mein Problem habe ich so gelöst:

        
      $text = 'blablabla... blablabla irgendwelche tags ... <img id="db1234" ..... /> blablabla ... blablabla <img id="db78" src="..." .... /> .. blablabla';		  
      $search = "/<img id=\"db[0-9]+\"/";  
      		  
      preg_match_all($search, $text, $matches);  
      		  
      $find_arr = array("<img id=\"db", "\"");  
      $repl_arr = array("", "");  
      		  
      $found_ids = str_replace($find_arr, $repl_arr, $matches[0]);  
      		  
      print_r($found_ids);  
      
      

      Der zugehörige Output:

        
      Array  
      (  
          [0] => 1234  
          [1] => 78  
      )  
      
      

      Das ist genau das was ich gesucht habe.

      1. $text = 'blablabla... blablabla irgendwelche tags ... <img id="db1234" ..... /> blablabla ... blablabla <img id="db78" src="..." .... /> .. blablabla';
        $search = "/<img id="db[0-9]+"/";

        preg_match_all($search, $text, $matches);

        $find_arr = array("<img id="db", """);
        $repl_arr = array("", "");

        $found_ids = str_replace($find_arr, $repl_arr, $matches[0]);

        print_r($found_ids);

        
        >   
        > Der zugehörige Output:  
        > ~~~html
          
        
        > Array  
        > (  
        >     [0] => 1234  
        >     [1] => 78  
        > )  
        > 
        
        

        Das ist genau das was ich gesucht habe.

        Da kannst du gleich mit preg_replace() ersetzen - ich verstehen den Sinn hinter der Aktion nicht ganz.

        1. Da kannst du gleich mit preg_replace() ersetzen - ich verstehen den Sinn hinter der Aktion nicht ganz.

          OK also so:
          um den variablen Zahlenteil im Suchmuster kommen Klammern rum:

          $search = "/<img id=\"db([0-9]+)\"/";

          Und die Erstetzung mittels so genannter "backreference" erfolgt dann so:
          $found_ids = preg_replace($search, "$1", $matches[0]);

          Somit bleibt vom gesamten Suchmuster nur mehr der Zahlenteil übrig. Das ist jetzt auch das, was ich eingangs von einer Variable gefaselt hatte :-)

          1. $found_ids = preg_replace($search, "$1", $matches[0]);

            Da stimmt aber jetzt etwas nicht - das erste Argument ist der Ausdruck, das Zweite die Ersetzung und das dritte der String in dem zu suchen ist - das ist in deinem Fall $text und nicht $matches[0].

            Das ist jetzt auch das, was ich eingangs von einer Variable gefaselt hatte :-)

            Nur verstanden hab' ichs nicht :D

            1. $found_ids = preg_replace($search, "$1", $matches[0]);

              Da stimmt aber jetzt etwas nicht - das erste Argument ist der Ausdruck, das Zweite die Ersetzung und das dritte der String in dem zu suchen ist - das ist in deinem Fall $text und nicht $matches[0].

              Das hab ich jetzt davon, dass ich nicht den ganzen Source von vorhin mit reingenommen hab ins neue Posting. $matches[0] ist ja bereits das Ergebnis von preg_match_all. Wenn du (chronologisch) von hinten nach vorne liest, verstehst du wie es funktioniert :-)

              1. $found_ids = preg_replace($search, "$1", $matches[0]);

                $matches[0] ist ja bereits das Ergebnis von preg_match_all. Wenn du (chronologisch) von hinten nach vorne liest, verstehst du wie es funktioniert :-)

                Ich sagte ja bereits: du kannst di  preg_match_all() komplett sparen nur _nur_ mit preg_replace() arbeiten.

  3. Hi,

    ein Pattern der Form "<img id="db%MYWILDCARD%", und als Ergebnis ein Array von gefundenen Wildcard-Werten zurückliefert.

    welchen Sinn macht so einw Wildcard wenn Du eh ein Pattern formulieren muss, das auch nix anderes als eine Regex darstellt... oder steh ich aufm Schlauch...?

    Dein Beispielproblem liesse sich etwa wie folgt lösen, vielleicht bringts Dich weiter:

    <?

    $str =  '<p><img id="db1234" src="foobar.gif" /></p><p><img src="foobar.gif" id="db4434" /></p><p><img alt="lala" id="db1223" src="foobar.gif" /></p></p><p><img src="foobar.gif" alt="lala" id="db1923"/></p>';
        $reg =  '#<img(.+?)(id="db(.+?)")(.*?)>#i';

    preg_match_all($reg, $str, $matches);

    echo "<pre>"; print_r($matches[3]); echo "</pre>"; die("kill");

    ?>

    Grüsse, Joachim

    Gruesse, Joachim

    --
    Am Ende wird alles gut.
    1. echo "<pre>"; print_r($matches[3]); echo "</pre>"; die("kill");

      Stringverkettung musst du noch üben :) oder dir ist der zweite Parameter ovn print_r() unbekannt.

      Zudem sind für dich sicher auch non-capturing parentheses interessant - warum dein Ausdruck so viel rausklezeln muss ist für mich nicht nachvollziehbar.

      Grüsse, Joachim
      Gruesse, Joachim

      DRY! Mann :p

      1. Hi,

        Stringverkettung musst du noch üben :)

        Das wäre nicht das Einzige... leider vergesse ich nach dem Üben immer alles ;-)

        warum dein Ausdruck so viel rausklezeln muss ist für mich nicht nachvollziehbar.

        Wollte mich halt nicht auf <img id="... verlassen. Aber in der Tat, die paar ? hätte ich spendieren können...

        Grüsse, Joachim
        Gruesse, Joachim

        Spätfolgen der gestrigen Weihnachtsfeier, ich steh nicht nur neben mir sondern sogar darunter ;-)

        Gruesse, Joachim

        --
        Am Ende wird alles gut.