preg_replace

Einklappen
X
 
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • preg_replace

    Ich schlag mich schon den ganzen mittag mit einem Regulären Ausdruck rum.

    PHP-Code:
    <?php
       $string
    ='<script language="JavaScript"> { { } </script>';
       
    $exp[]='/(<script.*)({(?!=|ldelim|rdelim))(.*<\/script>)/ums';
       
    $exp[]='/(<script.*)((?<!=|ldelim|rdelim)})(.*<\/script>)/ums';
       
    $rpl[]='${1}{ldelim}${3}';
       
    $rpl[]='${1}{rdelim}${3}';
       echo 
    var_dump($string=preg_replace($exp,$rpl,$string,-1));
    ?>
    Und zwar will ich zur Vorbereitung für das Parsen eines Smarty Templates alle { } durch {rdelim} und {ldelim} ersetzen. Die Funktion ersetzt nicht wie zu erwarten alle Vorkommen, sondern nur eines.

    Wie kann man das ändern? Ich hab das auch schon mit preg_replace_callback versucht, aber der liefert auch nur das letzte vorkommen.

    string(60) "<script language="JavaScript"> { {ldelim} {rdelim} </script>"
    Wie man sieht ist das erste { nicht umgesetzt.
    Zuletzt geändert von p_rehm; 18.07.2006, 19:30.

  • #2
    Re: preg_replace

    alle { } durch {rdelim} und {ldelim}
    Wieso hast Du dann noch den JS-Tag angegeben? Das ist der Knackpunkt ... Wende die Funktion mal doppelt auf den Text an, beim zweiten Mal natürlich auf den geänderten (keine endgültige Lösung, nur das Dus siehst).

    Das preg_replace() und preg_replace_callback() gleiche Stellen finden, liegt in der Natur der Sache.
    Die Zeit hat ihre Kinder längst gefressen

    Kommentar


    • #3
      Ja klar, aber das Problem ist dass ich nur die {_} in dem script tag ersetzen will, wenn ich die <script> beschränkung rausnehme ersetzt er alles.

      Irgendwie muss doch auch das möglich sein, oder?

      Kommentar


      • #4
        Irgendwie muss doch auch das möglich sein, oder?
        Ja, möglich ists.

        Wenn Dus über zusätzliche Assertions nicht (zeitnah) hinbekommst, kannst Du (da es wohl eine einmalige/seltene Aktion ist) preg_split() verwenden, jeweils auf den gesamten Script-Bereich splitten (als Subpattern definiert, mit delim_capture), das Array durchlaufen und in jedem zweiten Element { } + assertion auf rdelim/ldelim (wie oben, ohne die JS-Tags) ersetzen, implode() und fertig.

        Schlage ich jetzt vor, weil das wesentlich schneller geht, als sich jetzt noch einen ewigen Ausdruck dafür auszudenken.

        Falls die Erklärung unverständlich ist, hier mal eine Analogie. Entfernt alle Leerzeilen im Text, außer in Textareas ... sollte prinzipiell das gleiche sein und sich dahingehend leicht anpassen lassen.
        PHP-Code:
              //
              // Inhalte in <textarea>s werden nicht ersetzt
              //
              
        $parts preg_split('#(<textarea[^>]*>.*</textarea>)#Uis'$c, -1PREG_SPLIT_DELIM_CAPTURE);
              
        //
              // Jeden Teil durchlaufen
              //
              
        foreach ($parts as $index => $part) {
                if (
        $index%2)
                  continue;
                
        //
                // Leerzeilen entfernen
                //
                
        $parts[$index] = preg_replace("#\n\s*\n#""\n"$part);
              }
              
        //
              // Teile wieder zusammensetzen
              //
              
        $c implode(''$parts); 
        Oder nicht? Vielleicht hat ja jemand noch eine bessere Idee.
        Die Zeit hat ihre Kinder längst gefressen

        Kommentar


        • #5
          dann hätte ich auch noch einen vorschlag:
          PHP-Code:
          $string='<script language="JavaScript"> { { } </script>';

          function 
          rpl($matches)
           {
            return 
          str_replace(array('{''}'), array('{rdelim}''{ldelim}'), $matches[0]);
           }

          $string=preg_replace_callback('|<script.+>(.+)</script>|isU''rpl'$string); 

          Kommentar


          • #6
            damit vergisst du aber den fall wenn bereits ein {ldelim} vorhanden ist

            ist echt eine verzwickte situation...

            Kommentar


            • #7
              ist echt eine verzwickte situation...
              Nein, wieso denn? Die Version von 3DMax ist doch wesentlich kürzer als meine.
              wenn bereits ein {ldelim} vorhanden ist
              Ja und? In der Callback kannst Du doch Deine Assertion verwenden!?
              Die Zeit hat ihre Kinder längst gefressen

              Kommentar


              • #8
                stimmt funktioniert wunderbar.

                vielen dank!

                Kommentar


                • #9
                  ist das Hauptproblem nicht in den kleinen u's, welche nicht Ungreedy sondern utf-8 heissen? Ungreedies sind grosse U's. Vielleicht hat es nachher noch andere Probleme wie die vorantworter gesehen haben.

                  Kommentar


                  • #10
                    Stimmt, dass könnte auch zu Problemen führen ... also U ergänzen und m gleich entfernen, ich sehe dort kein ^ oder $ ... und wenn Du u nicht brauchst, das auch entfernen.
                    Die Zeit hat ihre Kinder längst gefressen

                    Kommentar


                    • #11
                      Original geschrieben von p_rehm
                      damit vergisst du aber den fall wenn bereits ein {ldelim} vorhanden ist
                      ja, hast recht - hätte ich ja auch vorm posten testen können. mein regex ist auch nicht sauber, aber egal, hast du ja jetzt hinbekommen.
                      könntest den fertigen code ja mal posten, falls mal jemand anders auch ein ähnliches problem hat.

                      Kommentar


                      • #12
                        PHP-Code:
                        /**
                        *    prepare for smarty removes the { } inside script tags to prepare for smarty
                        */
                        function makeSmartyReady($string)
                        {
                            return 
                        preg_replace_callback('|<script.+>(.+)</script>|isU''makeSmartyReadyReplace'$string);
                        }

                        /**
                        *    Only the callback for the preg_replace function
                        */
                        function makeSmartyReadyReplace($matches)
                        {
                            
                        $exp[]='/{(?!=|ldelim|rdelim)/U';
                            
                        $exp[]='/(?<!=|ldelim|rdelim)}/U';
                            
                        $rpl[]='${1}{ldelim}${3}';
                            
                        $rpl[]='${1}{rdelim}${3}';
                            
                        $arr=preg_replace($exp,$rpl,$matches); 
                            return 
                        $arr[0];

                        hier mein code

                        vielen dank nochmals.
                        Zuletzt geändert von p_rehm; 19.07.2006, 09:45.

                        Kommentar


                        • #13
                          jedenfalls stehen die kleinen u's auch hier wieder da, und das m ist auch noch da.

                          Frager kann schreiben, aber nicht lesen.

                          Kommentar

                          Lädt...
                          X