AndreD: Hilfe zu regulären Ausdrücken

Hallo zusammen,

also reguläre Ausdrücke sind nicht meine Welt... Ich möchte mittels preg_replace einen Teil einer URL tauschen, unabhängig was vor oder nach dem zu tauschenden Teil steht. Einschränken möchte ich es wie folgt in einem Testbeispiel:

<?php

$lang = "de";
$cat = "12";
$id = "123";

$url = "index.php?lang=" . $lang . "&cat=" . $cat . "&id=" . $id;

echo( "<p><b>Alte URL:</b> " . $url . "</p>" );

$lang = "en";

$url = preg_replace( "/^?lang=[a-z]{2}&?$/", $lang, $url)

echo( "<p><b>Neue URL:</b> " . $url . "</p>" );

?>

Also jeder String zwischen ?lang= und optional & der zwei beliebige Kleinbuchstaben enthält soll gegen $lang getauscht werden, leider tut sich nix.

Kann mir bitte jemand der sich ein wenig mit reg. Exp. auskennt auf die Sprünge helfen? Geht das überhaupt so oder brauch ich da ein komplexeres Pattern?

Vielen Dank & Gruss
AndreD

  1. Moin,

    $url = "index.php?lang=" . $lang . "&cat=" . $cat . "&id=" . $id;

    ^^^^^^^^^                   ^^^^

    $url = preg_replace( "/^?lang=[a-z]{2}&?$/", $lang, $url)

    ^^^               ^^^

    Fällt dir was auf?

    Kann mir bitte jemand der sich ein wenig mit reg. Exp. auskennt auf die Sprünge helfen? Geht das überhaupt so oder brauch ich da ein komplexeres Pattern?

    Ein wenig komplexer muß es schon sein. Damit würdest du nämlich "?lang=foo" durch "en" ersetzen. Du solltest also noch den Teil vor dem zu ersetzenden und den dahinter mit subpatterns einfangen und in einzusetzenden String schreiben:

    preg_replace("/(?lang=)[a-z]{2}(&?)/", "\1".$lang."\2",$url)

    --
    Henryk Plötz
    Grüße aus Berlin
    ~~~~~~~~ Un-CDs, nein danke! http://www.heise.de/ct/cd-register/ ~~~~~~~~
    ~~ Help Microsoft fight software piracy: Give Linux to a friend today! ~~
    1. Moin,

      Hallo Henryk,
      Danke erstmal für die fixe Antwort!

      Fällt dir was auf?

      Ja, ich dachte mir schon das es so irgendwie nicht wirklich klappen kann :-)

      Ein wenig komplexer muß es schon sein. Damit würdest du nämlich "?lang=foo" durch "en" ersetzen.

      Soweit war ich gestern schon, heut hats leider auch noch nicht hingehauen! :-)

      Du solltest also noch den Teil vor dem zu ersetzenden und den dahinter mit subpatterns einfangen und in einzusetzenden String schreiben:

      Hab noch nie was mit subpattern gemacht. Heisst dass, das alles was in () steht ein subpattern ist und diese entsprechend im replacement per \1 fürs erste und \2 fürs zweite einfügen kann?

      preg_replace("/(?lang=)[a-z]{2}(&?)/", "\1".$lang."\2",$url)

      Danke mal für Dein Beispiel, funktioniert im Augenblick leider noch nicht, ist aber auf jeden Fall eine sehr gute Grundlage um darauf aufzubauen :-)

      Gruss
      AndreD

      1. Hallo Henryk,

        Danke nochmal für Deine Hilfe! Wenn ich mir den regEx jetzt so anschau, ist es eigentlich nicht wirklich schwer :-) Mit den Subpattern kann man ja dann eigentlich recht viel lösen, ich denke ich werde mich in Zukunft ein wenig intensiver mit regEx auseinandersetzen.

        Danke & Gruss
        AndreD

    2. hi!

      preg_replace("/(?lang=)[a-z]{2}(&?)/", "\1".$lang."\2",$url)

      welche vor-/nachteile sind hier gegenueber
      preg_replace("/(?<=?lang=)[a-z]{2}(?=&?)/", $lang, $url);
      zu verzeichnen? oder machen die beiden gar nicht wirklich das gleiche?

      prost
      seth

      1. Moin,

        preg_replace("/(?lang=)[a-z]{2}(&?)/", "\1".$lang."\2",$url)
        welche vor-/nachteile sind hier gegenueber
        preg_replace("/(?<=?lang=)[a-z]{2}(?=&?)/", $lang, $url);
        zu verzeichnen? oder machen die beiden gar nicht wirklich das gleiche?

        Welchen Teil von

        Damit würdest du nämlich "?lang=foo" durch "en" ersetzen.

        habe ich undeutlich getippt? (Zugegebenermaßen habe ich nicht darauf geachtet, dass der regexp nur zweibuchstabige lang-Werte im $url akzeptiert. Er würde also 'nur' "?lang=fo" ersetzen und das letzte "o" lassen.)

        Ein Beispiel zur Klarheit:
        preg_replace("/(?lang=)[a-z]{2}(&?)/", "\1".$lang."\2", $url)
        $url vorher: foobar.htm?lang=ab
        $url nachher: foobar.htm?lang=en

        preg_replace("/(?lang=)[a-z]{2}(&?)/", $lang, $url)
        $url vorher: foobar.htm?lang=ab
        $url nachher: foobar.htmen

        --
        Henryk Plötz
        Grüße aus Berlin
        ~~~~~~~~ Un-CDs, nein danke! http://www.heise.de/ct/cd-register/ ~~~~~~~~
        ~~ Help Microsoft fight software piracy: Give Linux to a friend today! ~~
        1. hi Henryk!

          hast meinen beitrag nicht richtig gelesen, denke ich. dass der urspruengliche loesungsansatz von AndreD nix taugt, ist mir auch klar. ich wollte nur wissen, ob eine ganz andere loesung des problems, welches von AndreD in [pref:t=44310&m=241602] gestellt wurde, naemlich eine loesung ueber assertions der von dir genannten ebenbuerdig ist oder sogar besser oder vielleicht schlechter... und warum... :-)

          prost
          seth

          1. Moin,

            hast meinen beitrag nicht richtig gelesen, denke ich. dass der urspruengliche loesungsansatz von AndreD nix taugt, ist mir auch klar. ich wollte nur wissen, ob eine ganz andere loesung des problems, welches von AndreD in [pref:t=44310&m=241602] gestellt wurde, naemlich eine loesung ueber assertions der von dir genannten ebenbuerdig ist oder sogar besser oder vielleicht schlechter... und warum... :-)

            Uups, sag' doch dass du da Assertions eingebaut hast. Die paar geänderten Pixel sehe ich sonst auf meinem Display doch gar nicht ;-)

            Also der Hauptnachteil besonders von Look-Behind-Assertions wie sie hier nötig sind dürfte die Geschwindigkeit sein. Laut Doku macht Look-Behind genau das was der Name sagt: Gehe im String noch mal ein paar Zeichen zurück und schau' ob es matcht.

            Ein kurzer Benchmark nach dem Anwendungsbeispiel von microtime() zeigt für 100.000 Durchläufe der beiden Beispiele: Mit den Subpatterns dauert es 0.9s und mit den Assertions 1.44s.

            --
            Henryk Plötz
            Grüße aus Berlin
            ~~~~~~~~ Un-CDs, nein danke! http://www.heise.de/ct/cd-register/ ~~~~~~~~
            ~~ Help Microsoft fight software piracy: Give Linux to a friend today! ~~
            1. hi Henryk!

              Uups, sag' doch dass du da Assertions eingebaut hast.

              ich hab da assertions eingebaut... ;-)

              Laut Doku macht Look-Behind genau das was der Name sagt: Gehe im String noch mal ein paar Zeichen zurück und schau' ob es matcht.

              ahja, ok, damit waer das geklaert. :-)

              [Benchmark]

              Mit den Subpatterns dauert es 0.9s und mit den Assertions 1.44s.

              uff! (kein internetkuerzel, nur ausruf des erstaunens)

              noch einen schoenen "tag des deutschen bieres".

              prost
              seth