a²: RegEx für Gurus

Hallo Zusammen,

ich verwende die Funktion
$theText = eregi_replace('(<font [^<]*color=["|']?([^ "']*)["|']?[^>].*>([^<]*)</font>)','<fillcolor={ cmyk ' . getColorForPDF('\2', 'c') . ' ' . getColorForPDF('\2', 'm') . ' ' . getColorForPDF('\2', 'y') . ' ' . getColorForPDF('\2', 'k') . ' }>\3<fillcolor={ ' . $sDefaultTextColor . ' }>', $theText);

um HTML Code für einen PDF Generator aufzubereiten.

Leider meint es meine Expression zu gut und macht aus

-----
<h2>Bellum?</h2>
<p>Gallia est omnis divisa in partes tres, quarum unam incolunt Belgae, aliam Aquitani, tertiam qui ipsorum lingua <font color="#635e4b">Celtae</font>, nostra Galli <&b>appellantur<&normal>. Hi omnes lingua, institutis, legibus inter se differunt. Gallos ab Aquitanis <font color="#ff3831">Garumna </font>flumen, a Belgis <font color="#01164d">Matrona </font>et Sequana dividit. </p>
<p>Horum omnium fortissimi sunt Belgae, propterea quod a cultu atque humanitate provinciae longissime absunt, minimeque ad eos mercatores saepe commeant atque ea quae ad effeminandos animos pertinent important, proximique sunt Germanis, qui trans Rhenum incolunt, quibuscum continenter bellum gerunt. </p>
-----

statt

-----
<h2>Bellum?</h2>
<p>Gallia est omnis divisa in partes tres, quarum unam incolunt Belgae, aliam Aquitani, tertiam qui ipsorum lingua <fillcolor={ cmyk C M Y K }>Celtae<fillcolor={ cmyk 1 1 1 1 }>, nostra Galli <&b>appellantur<&normal>. Hi omnes lingua, institutis, legibus inter se differunt. Gallos ab Aquitanis <fillcolor={ cmyk C M Y K }>Garumna <fillcolor={ cmyk 1 1 1 1 }>flumen, a Belgis <fillcolor={ cmyk C M Y K }>Matrona <fillcolor={ cmyk 1 1 1 1 }>et Sequana dividit. </p>
<p>Horum omnium fortissimi sunt Belgae, propterea quod a cultu atque humanitate provinciae longissime absunt, minimeque ad eos mercatores saepe commeant atque ea quae ad effeminandos animos pertinent important, proximique sunt Germanis, qui trans Rhenum incolunt, quibuscum continenter bellum gerunt. </p>
-----

das hier:

-----
<h2>Bellum?</h2>
<p>Gallia est omnis divisa in partes tres, quarum unam incolunt Belgae, aliam Aquitani, tertiam qui ipsorum lingua <fillcolor={ cmyk 0 0.1 0.1 0.09 }>Matrona <fillcolor={ cmyk 1 1 1 1 }>et Sequana dividit. </p>
<p>Horum omnium fortissimi sunt Belgae, propterea quod a cultu atque humanitate provinciae longissime absunt, minimeque ad eos mercatores saepe commeant atque ea quae ad effeminandos animos pertinent important, proximique sunt Germanis, qui trans Rhenum incolunt, quibuscum continenter bellum gerunt. </p>
-----

Ganz abgesehen davon, dass meine Umwandlungsfunktion für hex nach RGB nicht stimmt ;-) , verschwindet der Text zwischen dem ersten öffnenden <font bis vor das letzte <font.
Warum? Eigentlich soll für jedes
<font>...</font> ein
<fillcolor={ cmyk C M Y K }>...<fillcolor={ cmyk 1 1 1 1 }>
gesetzt werden.
Ich komme leider nicht drauf was hier nicht passt und bin für jeden Tipp dankbar.

Beste Grüße

  1. Hi a²,

    Leider meint es meine Expression zu gut

    Du hast (vermutlich) das altbekannte Problem mit der Gefräßigkeit von Regulären Ausdrücken - merke dir: Ein regulärer Ausdruck will immer auf so viel passen, wie nur irgendwie möglich!

    Es gibt aber eine Option, wie du dieses Verhalten ändern kannst, sodass der RegEx so wenig wie möglich nimmt, wenn du PCRE RegEx nimmst, geht das mit dem Modifier U.

    Allerdings ist mir für eregi_replace() keine Möglichkeit bekannt, wie du dort das U Modifier mit übergeben kannst, ich würde dir deshalb dringend empfehlen, die "Vollversion" von eregi_replace, nämlich preg_replace() zu verwenden. [1]

    Dazu musst du deinen regulären Ausdruck zwischen zwei / setzen und jedes / im RegEx mit einem \ escapen, das gibt dann:

    /<dein RegEx>/

    Damit jetzt nicht auf Groß- und Kleinschreibung geachtet wird, hängst du ein i an und für die Ungefräßigkeit ein U:

    /<dein RegEx>/iU

    Probier das einfach mal und melde dich dann hier noch mal.

    MfG, Dennis.

    [1] Das PHP Manual empfiehlt übrigens die Verwendung der PCRE Funktionen gegenüber der POSIX-Funktionen (dazu gehört eregi_replace u.a.).

    1. Hallo Dennis.

      Dazu musst du deinen regulären Ausdruck zwischen zwei / setzen und jedes / im RegEx mit einem \ escapen, das gibt dann:

      Alternativ kann natürlich auch ein anderer Delimiter gewählt werden.

      Einen schönen Donnerstag noch.

      Gruß, Ashura

      --
      sh:( fo:} ch:? rl:( br: n4:~ ie:{ mo:| va:) de:> zu:} fl:( ss:) ls:[ js:|
      mathbr:del.icio.us/ mathbr:w00t/
    2. Hallo Ashura,

      vielen Dank für die hilfreiche und ausführliche AW :-)

      Bin der Gefräßigkeit nun doch Herr geworden, indem ich das ".*>" aus der Expression entfernt habe; hilfreich war dabei auch das Tool RegEx Coach, das ich jedem nur ans Herz legen kann, der solche Bandüwrmer debuggen will. Das Ergebnis ist nun:

      $theText = eregi_replace('(<font [^<]*color=["|']?([^ "']*)["|']?^></font>)','<fillcolor={ cmyk ' . getColorForPDF('\2', 'c') . ' ' . getColorForPDF('\2', 'm') . ' ' . getColorForPDF('\2', 'y') . ' ' . getColorForPDF('\2', 'k') . ' }\3<fillcolor={ ' . $sDefaultTextColor . ' }>', $theText);

      Soweit wird nun alles ersetzt bzw. die Tags entsprechend ausgetauscht. Leider gibt es nun ein weiteres Problem: auf \3 kann ich bequem zugreifen, jedoch wird statt \2 (das den Hexwert der Farbe enthalten sollte) an meine getColorForPDF()-Funktion immer die Ziffer 2 übergeben. Was mache ich hier falsch?

      Beste Grüße

      1. Hallo a².

        Hallo Ashura,

        vielen Dank für die hilfreiche und ausführliche AW :-)

        Dies ist aber nicht auf meinem Mist gewachsen.

        Einen schönen Freitag noch.

        Gruß, Ashura

        --
        sh:( fo:} ch:? rl:( br: n4:~ ie:{ mo:| va:) de:> zu:} fl:( ss:) ls:[ js:|
        mathbr:del.icio.us/ mathbr:w00t/
  2. *snip*

    So, alles erst mal wegwerfen, verwirrt nur ;-)

    Denn Konfuzius sagte schon damals:

    Wenn RegEx nix machen was Du wollen, Du RegEx machen ganz kurz fuer einfache Ersetzen, sehen, ob tut, dann Du machen RegEx immer komplizierter bis am Ende RegEx machen, was Du wollen !

    Gruß

    Hans

  3. ...was mir noch aufgefallen ist: Warum ist der Zugriff auf \2 nicht möglich? ;-)

    1. Hallo a².

      ...was mir noch aufgefallen ist: Warum ist der Zugriff auf \2 nicht möglich? ;-)

      Finde heraus, ob darin wirklich das liegt, was du erwartest.

      Einen schönen Donnerstag noch.

      Gruß, Ashura

      --
      sh:( fo:} ch:? rl:( br: n4:~ ie:{ mo:| va:) de:> zu:} fl:( ss:) ls:[ js:|
      mathbr:del.icio.us/ mathbr:w00t/