Stefano: Regulärer Ausdruck macht nicht ganz, was er soll

Hallo,

Ich möchte aus einer URL die Seitenanzahl herauslöschen:

$url = preg_replace("!&site=(.*?)&!","&",$url);

Ich habe den Eindruck, dass das funktioniert, bis &site=123 nur einmal in der URL vorkommt. Zu 99% kann ich ohnehin davon ausgehen, dass das so ist.

Wie aber kann ich die RegEx umbauen, dass site=... auch mehrfach vorkommen darf und allesamt ersetzt werden?

Grüße, Stefan

  1. Hallo,

    Ich möchte aus einer URL die Seitenanzahl herauslöschen:

    $url = preg_replace("!&site=(.*?)&!","&",$url);

    Offenbar mehr als nur die Zahl.

    Ich habe den Eindruck, dass das funktioniert, bis &site=123 nur einmal in der URL vorkommt. Zu 99% kann ich ohnehin davon ausgehen, dass das so ist.

    Den Eindruck? Worauf berut der?
    Und meinst Du "_solange_ &site=123 nur einmal in der URL vorkommt" oder wirklich "bis"?

    Wie aber kann ich die RegEx umbauen, dass site=... auch mehrfach vorkommen darf und allesamt ersetzt werden?

    In welchem Fall (konkretes Beispiel) wird es denn nicht ersetzt?

    1. In welchem Fall (konkretes Beispiel) wird es denn nicht ersetzt?

      siehe hier

      Grüße, Stefan

      1. In welchem Fall (konkretes Beispiel) wird es denn nicht ersetzt?

        siehe hier

        Grüße, Stefan

        Ich meinte natürlich

        siehe hier

        Grüße, Stefan

        1. siehe hier

          MudGuards Aufzählung der eingetretenen und weiteren möglichen Fallstricke scheint mir vollständig zu sein.

  2. Wie aber kann ich die RegEx umbauen, dass site=... auch mehrfach vorkommen darf und allesamt ersetzt werden?

    "Some people, when confronted with a problem, think 'I know, I’ll use regular expressions.' Now they have two problems." --Jamie Zawinski

    Eine Lösung mit parse_str() sagt dir nicht zu?

    1. Eine Lösung mit parse_str() sagt dir nicht zu?

      Doch, total. Kannte ich nur nicht.

      Kannst Du mir trotzdem der Vollständigkeit halber sagen, wie ich alle site=... ersetzen würde?

      Grüße, Stefan

      1. Hello,

        Eine Lösung mit parse_str() sagt dir nicht zu?

        Doch, total. Kannte ich nur nicht.

        Kannst Du mir trotzdem der Vollständigkeit halber sagen, wie ich alle site=... ersetzen würde?

        Es gibt nur ein site=... in den geparsten Variablen.

        1. parsen
        2. unset($_parsed_vars['site'])
        3. url neu aufbauen aus dem Ressourceanteil und den verbliebenen Elementen des Arrays

        Liebe Grüße aus dem schönen Oberharz

        Tom vom Berg

        --
         ☻_
        /▌
        / \ Nur selber lernen macht schlau
        http://bergpost.annerschbarrich.de
        1. Es gibt nur ein site=... in den geparsten Variablen.

          1. parsen
          2. unset($_parsed_vars['site'])
          3. url neu aufbauen aus dem Ressourceanteil und den verbliebenen Elementen des Arrays

          Ja klar. Über den Lösungsweg weiß ich nun schon, wie ichs mache.

          Trotzdem lässt mich nicht los, warum preg_replace nicht so gearbeitet hatte, wie ich dachte. Und das wurmt mich einfach.

            
          $test="text&site=234&text2=www&site=567&site=54332&text";  
            
          $test = preg_replace("!&site=(.*?)&!","&",$test);  
            
          echo $test; // Ergebniss: text&text2=www&site=54332&text  
          
          

          Grüße, Stefan

          1. $test="text&site=234&text2=www&site=567&site=54332&text";

            $test = preg_replace("!&site=(.*?)&!","&",$test);

            Weil das &site=567& findet und dann site=54332& nicht mehr macht - vermute ich.

            1. $test="text&site=234&text2=www&site=567&site=54332&text";

              $test = preg_replace("!&site=(.*?)&!","&",$test);

              Weil das &site=567& findet und dann site=54332& nicht mehr macht - vermute ich.

              Na, dann aber 3 Fragen hierzu:

              Die Regex hat ja sowohl &site=234& gefunden und ersetzt, als auch &site=567&.

              1. Warum dann nur das letzte nicht?
              2. Wo ist die Logik dahinter?
              3. Wie gestalte ich den Ausdruck entsprechend gieriger?

              Grüße, Stefan

                1. Warum dann nur das letzte nicht?
                2. Wo ist die Logik dahinter?

                $test="text&site=234&text2=www&site=567&site=54332&text";

                $test="text <- kein match
                &site=234& <- match
                text2=www <- kein match
                &site=567& <- match
                site=54332&text";  <- kein match

              1. Hallo,

                Die Regex hat ja sowohl &site=234& gefunden und ersetzt, als auch &site=567&.

                ja, jeweils einzeln.

                1. Warum dann nur das letzte nicht?
                2. Wo ist die Logik dahinter?

                Der gesuchte Ausdruck wird einmal gefunden (und ggf. ersetzt). Dann ist dieser Teil des Patterns aus dem Suchmuster "verbraucht".

                1. Wie gestalte ich den Ausdruck entsprechend gieriger?

                In deinem Sinn: Gar nicht. Einen Teil des Suchmusters mehrmals an verschiedenen Stellen zu finden, widerspricht dem Konzept: Pattern und der durchsuchte String lassen sich immer blockweise einander zuordnen, also jedem Abschnitt des Patterns entspricht auch ein Abschnitt im String (oder kann bei Verwendung der Quantifier ? oder * auch entfallen). Keinesfalls kann ein Abschnitt des Patterns mehreren Abschnitten im String entsprechen.

                So long,
                 Martin

                --
                Zwei Politiker auf dem Weg zum Sitzungssaal: "Was sagten Sie in ihrer Rede neulich noch zur Rentenreform?" - "Nichts." - "Ja, schon klar. Aber wie haben Sie es formuliert?"
                Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(
                  1. Wie gestalte ich den Ausdruck entsprechend gieriger?

                  In deinem Sinn: Gar nicht.

                  Bestenfalls die funktion mehrfach aufrufen, in diesem speziellen fall sollte 2 Aufrufe reichen.

              2. Hi,

                $test="text&site=234&text2=www&site=567&site=54332&text";
                $test = preg_replace("!&site=(.*?)&!","&",$test);
                Weil das &site=567& findet und dann site=54332& nicht mehr macht - vermute ich.

                Richtig vermutet.

                Na, dann aber 3 Fragen hierzu:
                Die Regex hat ja sowohl &site=234& gefunden und ersetzt, als auch &site=567&.

                1. Warum dann nur das letzte nicht?

                Weil diese Fundstelle mit der vorherigen überlappt.

                1. Wo ist die Logik dahinter?

                für einen weiteren Versuch wird NACH der vorherigen Fund-/Ersetzungsstelle begonnen.
                Das & vor dem letzten Site ist Bestandteil der vorletzten Fund-/Ersetzungsstelle.

                1. Wie gestalte ich den Ausdruck entsprechend gieriger?

                Indem Du das & am Anfang der Fundstelle nicht matchst, sondern per lookbehind einbindest.
                Und auch gleich noch den Fall berücksichtigst, daß vor dem ersten Parameter kein & steht, sondern ein ?.
                Und wenn Du schon dabei bist, auch gleich noch das ; als Parametertrennung berücksichtigen.

                Ach ja, wenn der site-Parameter der letzte Parameter in der URL ist, wird er auch nicht ersetzt werden, da kein & mehr folgt.

                Da der Parameterwert kein & oder ; enthalten darf, wäre es besser, statt (.*?)& besser [^&;]+ zu verwenden. Dann klappt's auch mit dem letzten Parameter.
                Damit kommt es auch nicht mehr zu Überlappungen bei ?site=1&site=2, da das & dazwischen kein Bestandteil der Fund-/Ersetzungsstelle ist.
                Die Ersetzung muß dann natürlich leer sein statt &

                cu,
                Andreas

                --
                Warum nennt sich Andreas hier MudGuard?
                O o ostern ...
                Fachfragen per Mail sind frech, werden ignoriert. Das Forum existiert.
                1. für einen weiteren Versuch wird NACH der vorherigen Fund-/Ersetzungsstelle begonnen.
                  Das & vor dem letzten Site ist Bestandteil der vorletzten Fund-/Ersetzungsstelle.

                  Verstehe.

                  @Andreas:

                  Vielen Dank für Deine Ausführungen, die ich verstehe. Einige dieser Fallstricke hatte ich bereits durch weitere reg_replace umgangen. Aber jetzt verstehe ich wenigstens, woran der Versuch über meine Regex gescheitert war.

                  @Suit: Danke für den Tip mit parse_str().
                  Ich habe nun das ganze Konstrukt umgebaut und mithilfe von parse_url() und parse_str() die URL zerlegt und wieder zusammengesetzt.

                  In diesem Fall ist das wirklich die sinnvollste Lösung, da ich als Endprodukt einen sehr kontrollierten String zusammenbasteln kann.

                  Funktioniert übrigens vorzüglich.

                  Danke auch an alle anderen am Thread beteiligten User.

                  Grüße, Stefan

                  P.S: Eine Frage vielleicht noch: In der Doku zu parse_url() steht, dass sie nicht mit relativen URL funktioniert. Meine sind aber relativ und der array-wert "host", "path" und "query" greifen dennoch die richtigen Inhalte ab.

                  Ist das Zufall und muss ich mir deshalb jetzt Sorgen machen?

                  1. Ich habe nun das ganze Konstrukt umgebaut und mithilfe von parse_url() und parse_str() die URL zerlegt und wieder zusammengesetzt.

                    Zawinski | PCRE
                    ---------+-----
                    1        | 0

                    :)

                    P.S: Eine Frage vielleicht noch: In der Doku zu parse_url() steht, dass sie nicht mit relativen URL funktioniert. Meine sind aber relativ und der array-wert "host", "path" und "query" greifen dennoch die richtigen Inhalte ab.

                    Das kommt darauf an, was du unter relativ verstehst :)

                    Wenn du damit einen absolute URL eben ohne protokoll und host meinst, ist er nicht relativ. Im Zweifelsfall knall einfach ein http://example.com davor und ignorier das beim zusammenbauen wieder.

  3. Ich möchte aus einer URL die Seitenanzahl herauslöschen:

    $url = preg_replace("!&site=(.*?)&!","&",$url);

    Ich habe den Eindruck, dass das funktioniert, bis &site=123 nur einmal in der URL vorkommt. Zu 99% kann ich ohnehin davon ausgehen, dass das so ist.

    Da hast du aber Glück, dass du dich nicht mit
     '&'
    versus HTML-gerechten '&amp;' herumschlagen musst

    Wie aber kann ich die RegEx umbauen, dass site=... auch mehrfach vorkommen darf und allesamt ersetzt werden?

    Mit einer vernünftigen callback routine, welche deine URL sicher zerlegt und dann auf den query parts entsprechende Manipulationen vornimmt.

    Da ist kein Grund anzunehmen, dass & der einzige legitime query part Separator ist.

    mfg Beat

    --
    ><o(((°>           ><o(((°>
       <°)))o><                     ><o(((°>o
    Der Valigator leibt diese Fische
    1. Mit einer vernünftigen callback routine, welche deine URL sicher zerlegt und dann auf den query parts entsprechende Manipulationen vornimmt.

      Wozu, es gibt fertige Funktionen dafür.

      1. Mit einer vernünftigen callback routine, welche deine URL sicher zerlegt und dann auf den query parts entsprechende Manipulationen vornimmt.

        Wozu, es gibt fertige Funktionen dafür.

        Was für ein idiotischer Funktionsname!

        mfg Beat

        --
        ><o(((°>           ><o(((°>
           <°)))o><                     ><o(((°>o
        Der Valigator leibt diese Fische