romy: preg_replace_callback-> Funktionsweise

Hi,

ich versuche eine Lin keersetzung mittels preg_replace_callback zu kreieren, leider scheitert es an einem kleinem Problem...

Wenn ich einfach nur die Funktion aufrufe und im gleichen Text eine andere (nämlich die callback-Funktion) definiert habe, funktioniert es tadellos.

Bsp. (von php.net)
<?php
  $text = "April fools day is 04/01/2002\n";
  $text.= "Last christmas was 12/24/2001\n";

// the callback function
  function next_year($matches) {
    // as usual: $matches[0] is the complete match
    // $matches[1] the match for the first subpattern
    // enclosed in '(...)' and so on
    return $matches[1].($matches[2]+1);
  }

echo preg_replace_callback(
              "|(\d{2}/\d{2}/)(\d{4})|",
              "next_year",
              $text);
?>

wenn ich jetzt aber den gesamten COde in einer FUnktion kapseln will, weiss ich nicht mehr wo die Callback-Funktion hinkommt. Innerhalb der Funktion wieder eine Funktion deklarieren finde ich komisch und einfach ausserhalb geht nicht. Ich weiss leider nicht was für ein FEhler auftritt, es erscheint nur die Ausgabe nicht richtig (bzw. gar nicht, wie in diesem Beispiel)

Beispiel:
<?php
function hallo() {
  $text = "April fools day is 04/01/2002\n";
  $text.= "Last christmas was 12/24/2001\n";

echo preg_replace_callback(
              "|(\d{2}/\d{2}/)(\d{4})|",
              "next_year",
              $text);
}

// the callback function
  function next_year($matches) {
       return $matches[1].($matches[2]+1);
  }

?>

Was kann ich da tun?

ciao
romy

--
DIE ROMY AUS L. AN DER P. SAGT DANKE UND AUF WIEDERSEHEN
sh:( fo:| ch:? rl:( br:& va:| zu:) ss:| ls:[
Die Erklärung zum Selfcode findest du hier: http://emmanuel.dammerer.at/selfcode.html
Einen Decoder für den Selfcode findest du hier: http://peter.in-berlin.de/projekte/selfcode
  1. Hi,

    okay es lag wohl an mir, dieses einfache Beispiel funktioniert
    ABER:

    Wenn ich jetzt die callback-funktion nicht $matches zurückgeben lasse, sondern nur 1 oder so, funktioniert auch dies bei diesem Beispiel okay. Versuche ich es auf meine Problematik zu münzen kommt nur Unsinn raus...

    beispiel
    <?php

    function setLink($file) {
     if(file_exists($file)){
      # file_string includes the whole site-string
      $file_string = implode("",(@file($file)));

    // in $file_string steht das drin was auch drinstehen soll, einfach eine //html-seite mit ein paar links und ein bisschen Schrift

    # finds a - tags
      $pattern = '=^(.*)<a(.*)href="?(\S+)"([^>]*)>(.*)</a>(.*)$=msi';

    return preg_replace_callback($pattern, "callback_setLink", $file_string);

    }else {
      return 0;
     }
    }

    function callback_setlink($matches){
     return 1;
    }

    ?>

    <html>
    <head>
    <title> test </title>
    </head>
    <body>
    <textarea style="width:400px; height:300px">

    <?
    echo setLink("test.html");
    ?>
    <!-- test.html
    blabaohdsf
    asdöfj
    sdfo
    <a href="test.htm">is</a>
    <a href="test.htm">is</a>
    <a href="test.htm">is</a>
    djoi

    -->
    </textarea>

    </body>
    </html>

    Ich würde nun vermuten das mir auch meine Seite mit der Schrift und anstatt der links nun eine 1 ausgegeben wird, aber nein es steht nur eine 1 da. Wohin ist  der Text?

    danke

    ciao
    romy

    --
    DIE ROMY AUS L. AN DER P. SAGT DANKE UND AUF WIEDERSEHEN
    sh:( fo:| ch:? rl:( br:& va:| zu:) ss:| ls:[
    Die Erklärung zum Selfcode findest du hier: http://emmanuel.dammerer.at/selfcode.html
    Einen Decoder für den Selfcode findest du hier: http://peter.in-berlin.de/projekte/selfcode
    1. Hi,

      naja, so komme ich nicht weiter...
      das eigentliche Problem besteht immernoch wie eh und je.
      Eigentlich wollte ich ja erreichen, dass alle matches gefunden und ersetzt werden, aber selbst preg_replace_callback, ersetzt jeweils nur das Erstgefundene. Wenn ich nicht in eine endlos-Schleife rutschen will muss ich mir also was anderes überlegen...aber was. Habe keine Funktion finden können, die das erfüllt was ich möchte und finde leider auch keinen Ansatz zum selber schreiben.

      Hat bitte jemand eine Idee?

      ciao
      romy

      --
      DIE ROMY AUS L. AN DER P. SAGT DANKE UND AUF WIEDERSEHEN
      sh:( fo:| ch:? rl:( br:& va:| zu:) ss:| ls:[
      Die Erklärung zum Selfcode findest du hier: http://emmanuel.dammerer.at/selfcode.html
      Einen Decoder für den Selfcode findest du hier: http://peter.in-berlin.de/projekte/selfcode
      1. Hi,

        des Rätsels Lösung könnten "Modifier" sein. Das sind Schalter/Parameter für die Verhaltensweise der Suche.

        Bye

        1. Sorry. Ich hatte übersehen, das Du solche schon benutzt:

          ...$=msi...

          1. Hi,

            ...$=msi...

            jaja trotzdem lag dort der Fehler, da m und s sich aufheben ;)
            <peinlich peinlich>

            Aber jetzt kommts: s bedeutet, der string wird zeilenweise durchgegangen (was ich möglichst nicht will) aber bei m solte eigentlich der gesamte String genommen werden. BEi meinen TEsts erzielten beide aber den gleichen Effekt (natürlich den den ich nicht möchte)

            das verstehe ich nicht wirklich...

            ciao
            romy

            --
            DIE ROMY AUS L. AN DER P. SAGT DANKE UND AUF WIEDERSEHEN
            sh:( fo:| ch:? rl:( br:& va:| zu:) ss:| ls:[
            Die Erklärung zum Selfcode findest du hier: http://emmanuel.dammerer.at/selfcode.html
            Einen Decoder für den Selfcode findest du hier: http://peter.in-berlin.de/projekte/selfcode
            1. Hello again,

              was ich nicht so ganz verstehe, ist das Suchmuster:

              $pattern = '=^(.*)<a(.*)href="?(\S+)"([^>]*)>(.*)</a>(.*)$=msi';

              Bist Du Dir denn im Klaren darüber, was da genau passiert? Ein Denkfehler? Vielleicht durchblicke ich es auch gar nicht, weil ich Dein Problem nicht verstanden habe... 8|

              =
                ^          <= Stringanfang
                (.*)       <= wozu diesen Teil Zwischenspeichern?
                <a
                  (.*)
                  href
                    =
                    "?
                    (\S+)
                    "      <= fehlt hier nicht auch ein Fragezeichen?
                  ([^>]*)
                  >
                  (.*)
                </a>
                (.*)       <= und wozu das, es gehört doch nicht mehr zum Link?
                $          <= Stringende

              msi

              ...was ja bedeuten würde, das bei dem ersten gefunden Muster bereits der komplette String maskiert wird. Dadurch kommt doch jetzt immer das gleiche Ergebnis zustande, oder?

              1. Hi,

                was ich nicht so ganz verstehe, ist das Suchmuster:

                $pattern = '=^(.*)<a(.*)href="?(\S+)"([^>]*)>(.*)</a>(.*)$=msi';
                Bist Du Dir denn im Klaren darüber, was da genau passiert?

                nur zur Hälfte leider...

                =
                  ^          <= Stringanfang
                  (.*)       <= wozu diesen Teil Zwischenspeichern?
                  <a
                    (.*)
                    href
                      =
                      "?
                      (\S+)
                      "      <= fehlt hier nicht auch ein Fragezeichen?

                ja, stimmt ich sehe es auch

                ([^>]*)
                    >
                    (.*)
                  </a>
                  (.*)       <= und wozu das, es gehört doch nicht mehr zum Link?
                  $          <= Stringende

                msi

                ich dachte (.*) sagt aus, egal was dort steht suche trotzdem nach <a
                Also das sozusagen beliebiger Text vor und nach dem link stehen kann.
                Wenn ich dies weglasse, wie kann ich dann den neuen STring wieder richtig zusammensetzen?

                Ich gebe mal ein Beispiel:

                bla
                böla
                bla
                <a href="bla"> bla </a>
                <a href="bla"> bla </a>
                <a href="bla"> bla </a>
                <gihf
                asdfj
                asdlf

                nach der Ersetzung sollte das Ganze so aussehen:

                bla
                böla
                bla
                <a href="bla?anderesbla=js&..."> bla </a>
                <a href="bla?anderesbla=js&..."> bla </a>
                <a href="bla?anderesbla=js&..."> bla </a>
                <gihf
                asdfj
                asdlf

                ausserdem brauche ich auch die targets, denn diese müssen sofern vorhanden auch mit in der querystring!

                ?

                vielen Dank für deine Mühen...

                ciao
                romy

                --
                DIE ROMY AUS L. AN DER P. SAGT DANKE UND AUF WIEDERSEHEN
                sh:( fo:| ch:? rl:( br:& va:| zu:) ss:| ls:[
                Die Erklärung zum Selfcode findest du hier: http://emmanuel.dammerer.at/selfcode.html
                Einen Decoder für den Selfcode findest du hier: http://peter.in-berlin.de/projekte/selfcode
                1. ich dachte (.*) sagt aus, egal was dort steht suche trotzdem nach <a Also das sozusagen beliebiger Text vor und nach dem link stehen kann.

                  Korrekt, das bewirkt .*
                  Und durch die Klammer wird dieser Teil dann für spätere Zugriffe intern zwischengespeichert.
                  Durch das Weglassen der Klammer kannst Du den neuen String nicht wieder zusammensetzen, weil Dir der Teil vor dem Link fehlt. Okay, das leuchtet ein.
                  Ich überlege mir mal, ob man unbedingt die Teile vor und nach dem Link extrahieren muß oder ob es nicht auch irgendwie anders geht...

                  Bis später

                  1. Hi,

                    Durch das Weglassen der Klammer kannst Du den neuen String nicht wieder zusammensetzen, weil Dir der Teil vor dem Link fehlt. Okay, das leuchtet ein.
                    Ich überlege mir mal, ob man unbedingt die Teile vor und nach dem Link extrahieren muß oder ob es nicht auch irgendwie anders geht...

                    danke, das wäre echt nett

                    Hätte noch ein großes Problem:
                    Ich muss damit rechenen, das links zB. so
                    eingeben werden
                    href = "bla"
                    href=bla
                    href= "bla"
                    href=" bla "

                    Immer wenn Leerzeichen auftreten funktioniert diese suche nicht mehr, was und wo muss ich einfügen um es korrekt funktionieren zu lassen?

                    bzw.

                    wenn dort steht
                    class="blA" target="bla" border="3"
                    hab ich eigentlich ne Möglichkeit gefunden, den Target zu extrahieren /(aber nur eigentlich ;))

                    preg_match('/target=(.*)/i',$string,$txt
                    allerdings liefert dies auch border="3" mit und ich möchte gern das die suche nach dem nächsten leerzeichen abbricht...

                    danke echt, Du hast mir schon sehr geholfen

                    ciao
                    romy

                    --
                    DIE ROMY AUS L. AN DER P. SAGT DANKE UND AUF WIEDERSEHEN
                    sh:( fo:| ch:? rl:( br:& va:| zu:) ss:| ls:[
                    Die Erklärung zum Selfcode findest du hier: http://emmanuel.dammerer.at/selfcode.html
                    Einen Decoder für den Selfcode findest du hier: http://peter.in-berlin.de/projekte/selfcode
                    1. Bitteschön! Okay, ich überleg mir was für möglichst alle Tag-Varianten von Kombinationen mit Zeilenwechseln, Leer- und Anführungszeichen... Das kann allerdings ein paar Tage dauern.

                      Eine Lösung für solche Fälle brauche ich wohl früher oder später selbst mal. Ich plane nämlich eine Art zentrale Link-Liste, wobei in (X)HTML nur eine Referenz darauf als XML-Tag im Code stehen soll, z.B. <a refid="foo"></a>. Mit PHP sollen dann anhand der ID zur Laufzeit Attribute wie href und target aus einem zentralen Array eingefügt werden. Das spart Verwaltungsarbeit.

                      Gruß
                      Danny

                    2. Hier mal ein möglicher Ansatz, wobei man sich die Teile vor und Nach dem Link nicht zu merken braucht, da das von den RegExp intern geregelt wird.

                      An die Funktion parse_links werden gültige Links übergeben und können manipuliert werden. Nach der Rückgabe erfolgt die Ersetzung im String automatisch...

                      <?php

                      function setLink($file)
                      {
                        if (file_exists($file)) {
                          $file_string = implode("", (@file($file)) );

                      $pattern = '/(<a.*>.*</a>)/me'; // e = Ersetzung mit eigener PHP-Funktion

                      $matches = preg_replace($pattern, 'parse_link("\1")', $file_string);
                          print_array($matches);

                      }
                        else {
                          return 0;
                        }
                      }

                      function parse_link($link)
                      {
                       return $link."<br />";
                      }

                      function print_array($var)
                      {
                       print "<textarea style="width: 950px; height:550px;">";
                       print_r ($var);
                       print "</textarea>";
                      }

                      setLink("test.html");

                      ?>

                      1. Hi,

                        Hier mal ein möglicher Ansatz, wobei man sich die Teile vor und Nach dem Link nicht zu merken braucht, da das von den RegExp intern geregelt wird.

                        danke schon mal  ich fand dies auf jeden Fall schon mal übersichtlicher, als meine Variante, im Moment tut es allerdings das Gleiche: d.h. das mit dem Umbruch ist wahrscheinlich ganz schön hart...

                        ich liege Dir zu Füssen ... ;)

                        ciao
                        romy

                        --
                        DIE ROMY AUS L. AN DER P. SAGT DANKE UND AUF WIEDERSEHEN
                        sh:( fo:| ch:? rl:( br:& va:| zu:) ss:| ls:[
                        Die Erklärung zum Selfcode findest du hier: http://emmanuel.dammerer.at/selfcode.html
                        Einen Decoder für den Selfcode findest du hier: http://peter.in-berlin.de/projekte/selfcode
    2. Hi Romy,

      den Text hast Du Dir selbst überschrieben, weil Du in der Callback-Funktion 1 zurückgegeben hast. Dies wird an das Echo weitergeleitet...

      Matches ist ein Array, das die gefundenen Teilmuster enthält. Und so mußt Du es auch behandeln.

      Gruß,
      Danny

      1. Hi,

        den Text hast Du Dir selbst überschrieben, weil Du in der Callback-Funktion 1 zurückgegeben hast. Dies wird an das Echo weitergeleitet...

        Matches ist ein Array, das die gefundenen Teilmuster enthält. Und so mußt Du es auch behandeln.

        I know I know ;)
        Bin auch schon drauf gekommen, ich muss natürlich den text, davor und danach wieder einsetzen...

        Leider waren dies nur die Problemchen...

        Ich könnte ja auch den Code zeilenweise einlesen und auch zeilenweise ersetzen, bloss was mache ich mit sowas:
        <a
        href=hasdj>dgf
        </a>

        dann ist es ja nicht mehr in einer Zeile...

        *quengel*

        ciao
        romy

        --
        DIE ROMY AUS L. AN DER P. SAGT DANKE UND AUF WIEDERSEHEN
        sh:( fo:| ch:? rl:( br:& va:| zu:) ss:| ls:[
        Die Erklärung zum Selfcode findest du hier: http://emmanuel.dammerer.at/selfcode.html
        Einen Decoder für den Selfcode findest du hier: http://peter.in-berlin.de/projekte/selfcode