mixmastertobsi: RegEX nicht erklärbar

Hallo, entweder bin ich "doof", oder hier liegt ein PHP-Fehler vor.

Ich versuche mit folgender Anweisung einen TEXT zu matchen. Der Unterschied zwischen ersten und zweiten TExt ist nur das letzte Wort "Eiche". Wenn ich das Wort großschreibe, findet er den Text NICHT und wenn ich es kleinschreibe, findet er den Text. Das ist doch nicht erklärbar - oder?

preg_match_all("/\[TEXT([0-9]*)\]([^\[\/TEXT\]]*)\[\/TEXT\]/s", $beschreibung, $match_text);
[TEXT48]

Diese Möbel sind solide und hochwertig gefertigt und bei guter Pflege unkaputtbar. Das zeitlose Design ist auch morgen noch schön und geht mit der wertvollen Wildeiche eine gelungene Liaison ein. Denn die Qualität beginnt mit der richtigen Auswahl des Rohmaterials und bedarf außerdem viel Liebe zum Detail. Schubladenführungen und Scharniere aus Metall halten den Belastungen des Alltags stand, eben wie die sprichwörtliche deutsche Eiche.

[/TEXT]

[TEXT48]

Diese Möbel sind solide und hochwertig gefertigt und bei guter Pflege unkaputtbar. Das zeitlose Design ist auch morgen noch schön und geht mit der wertvollen Wildeiche eine gelungene Liaison ein. Denn die Qualität beginnt mit der richtigen Auswahl des Rohmaterials und bedarf außerdem viel Liebe zum Detail. Schubladenführungen und Scharniere aus Metall halten den Belastungen des Alltags stand, eben wie die sprichwörtliche deutsche eiche.

[/TEXT]
  1. @@mixmastertobsi

    Hallo, entweder bin ich "doof", oder hier liegt ein PHP-Fehler vor.

    Wenn Wetten angenommen werden, setze ich auf ersteres. ;-)

    Ich versuche mit folgender Anweisung einen TEXT zu matchen. Der Unterschied zwischen ersten und zweiten TExt ist nur das letzte Wort "Eiche". Wenn ich das Wort großschreibe, findet er den Text NICHT und wenn ich es kleinschreibe, findet er den Text. Das ist doch nicht erklärbar - oder?

    preg_match_all("/\[TEXT([0-9]*)\]([^\[\/TEXT\]]*)\[\/TEXT\]/s", $beschreibung, $match_text);
    

    ([^\[\/TEXT\]]*) heißt: zwischen [TEXT48] und [/TEXT] sind beliebig viele Zeichen außer [, /, T, E, X, T und ] erlaubt.

    „Eiche“ enthält aber ein großes E, deshalb matcht das nicht.

    LLAP 🖖

    --
    “You might believe there are benefits for the developer, but first of all, you should put those behind the interest of the user.” —Stefan Tilkov
    Selfcode: sh:) fo:} ch:? rl:) br:> n4:& va:| de:> zu:} fl:{ ss:| ls:# js:|
  2. Hi,

    Ich versuche mit folgender Anweisung einen TEXT zu matchen. Der Unterschied zwischen ersten und zweiten TExt ist nur das letzte Wort "Eiche". Wenn ich das Wort großschreibe, findet er den Text NICHT und wenn ich es kleinschreibe, findet er den Text. Das ist doch nicht erklärbar - oder?

    preg_match_all("/\[TEXT([0-9]*)\]([^\[\/TEXT\]]*)\[\/TEXT\]/s", $beschreibung, $match_text);
    

    doch, eigentlich schon. Es liegt daran, dass du im mittleren Teil deines RegEx eine Zeichenklasse notiert hast. Du willst also zwischen deinen Begrenzern alles finden, was

    • keine öffnende oder schließende eckige Klammer
    • kein Slash
    • und keiner der Großbuchstaben T, E oder X ist (das T steht sogar doppelt drin).

    Im Wort "Eiche" steht aber ein großes E, das nach deiner Regel nicht vorkommen darf, also endet der gefundene Teil vor dem E. Danach folgt aber nicht der String [/TEXT], also passt das Suchmuster nicht auf den gesamten Text.
    Denselben Effekt hättest du, wenn zufällig ein anderes Wort vorkäme, das mit T, E oder X beginnt.

    So long,
     Martin

    1. Hallo, OK verstanden ;) aber wie kann ich nur angeben, dass alles erlaubt ist, bis auf [/TEXT]. Also nicht die einzelnen Buchstaben, sondern die Wortkombi.

      1. Hallo mixmastertobsi,

        Hallo, OK verstanden ;) aber wie kann ich nur angeben, dass alles erlaubt ist, bis auf [/TEXT]. Also nicht die einzelnen Buchstaben, sondern die Wortkombi.

        Zeichen, die in einem bestimmten Kontext eine Sonderbedeutung haben, …

        Bis demnächst
        Matthias

        --
        Wenn eine Idee nicht zuerst absurd erscheint, taugt sie nichts. (Albert Einstein)
        1. Hallo Matthias,

          Hallo, OK verstanden ;) aber wie kann ich nur angeben, dass alles erlaubt ist, bis auf [/TEXT]. Also nicht die einzelnen Buchstaben, sondern die Wortkombi.

          Zeichen, die in einem bestimmten Kontext eine Sonderbedeutung haben, …

          Was Matthias vermutlich sagen will: Auch wenn die Regex-Engines heutzutage ziemlich ausgefeilt sind und reguläre Ausdrücke oft nicht mehr regulär sind, sind reguläre Ausdrücke keine Parser. Sie eignen sich zur Mustererkennung, für mehr musst du selber mehr Arbeit leisten.

          Ich an deiner Stelle würde, wenn ich einen Parser schreiben müsste, mir mal PEG anschauen, auch PHP hat dafür fertige Module, etwa https://github.com/hafriedlander/php-peg.

          LG,
          CK

        2. Hallo,

          aber wie kann ich nur angeben, dass alles erlaubt ist, bis auf [/TEXT].
          Also nicht die einzelnen Buchstaben, sondern die Wortkombi.

          Zeichen, die in einem bestimmten Kontext eine Sonderbedeutung haben, …

          ... hat er ja konsequent und korrekt maskiert. Das ist hier nicht der Punkt, der Hinweis ist IMO nicht zielführend.

          Aber den richtigen Hinweis hat MudGuard ja schon gegeben. Das "alles, bis auf ..." ergibt sich damit implizit dadurch, dass die Zeichenfolge [/TEXT] am Ende vorkommen muss.

          Ciao,
           Martin

  3. Hi,

    preg_match_all("/\[TEXT([0-9]*)\]([^\[\/TEXT\]]*)\[\/TEXT\]/s", $beschreibung, $match_text);
    

    Du schließt in der Mitte per [^[/TEXT]] die Großbuchstaben T, E und X aus.
    Und wunderst Dich dann, daß der Text nicht gematcht wird, wenn ein E drinsteckt.

    Für den Text zwischen den "Tags" reicht ein (.*?) aus.

    cu,
    Andreas a/k/a MudGuard

    1. Hallo MudGuard,

      Für den Text zwischen den "Tags" reicht ein (.*?) aus.

      Wenn man Fehler und Verschachtelungen ignoriert.

      LG,
      CK

      1. Hallo und Danke, aber das .* reicht hier nicht aus, denn was mache ich, wenn der String so aussieht

        [TEXT1] blablabla [/TEXT]

        [TEXT2] blablabla [/TEXT]

        In dem Beispiel würde als Inhalt folgendes erkennen

        blablabla [/TEXT] [TEXT2] blablabla

        1. Hallo mixmastertobsi,

          Hallo und Danke, aber das .* reicht hier nicht aus, denn was mache ich, wenn der String so aussieht

          Genau lesen ;-) Mudguard schrieb was von .*?.

          LG,
          CK

          1. Ist doch das selbe, oder was bewirkt das "?"

            1. Hallo mixmastertobsi,

              Ist doch das selbe, oder was bewirkt das "?"

              Es ist weder das selbe noch das gleiche. Das Fragezeichen hinter einem Quantifikator stellt dessen Greedyness aus. Das hättest du aber auch im Manual nachlesen können :)

              LG,
              CK

              1. So'n Mist. Meine Suchanfrage nach 'greedyness regex' führt mich unter anderem auf eine Seite mit dem Titel 'Greedy and Lazy' auf Javascript.info.

                hoffentlich hat keiner bemerkt wie ich mich angesprochen gefühlt hatte :D

                Vielen Dank für eure Beiträge zu dem Thema/Thread und sorry für den OT-Post... run&hide

              2. Hallo,

                Das Fragezeichen hinter einem Quantifikator stellt dessen Geedyness aus.

                ich schenke dir noch ein 'r'. ;-)

                Und die Prosa-Erklärung dazu: Die Quantifier * (beliebig viel) und + (beliebig viel, aber mindestens eins) matchen normalerweise so viele Vorkommen wie nur möglich, sie sind "greedy" (gierig).
                Mit dem nachgestellten Fragezeichen werden sie plötzlich bescheiden und matchen sie dagegen nur so wenige Vorkommen, wie es für das Suchmuster minimal nötig ist.

                So long,
                 Martin

                1. @@Der Martin

                  … stellt dessen Geedyness aus.

                  ich schenke dir noch ein 'r'. ;-)

                  Und ich dachte, „Geekyness“ war gemeint.

                  LLAP 🖖

                  --
                  “You might believe there are benefits for the developer, but first of all, you should put those behind the interest of the user.” —Stefan Tilkov
                  Selfcode: sh:) fo:} ch:? rl:) br:> n4:& va:| de:> zu:} fl:{ ss:| ls:# js:|
      2. Hi,

        Wenn man Fehler und Verschachtelungen ignoriert.

        Verschachtelungen wollte der OP offensichtlich nicht.

        Und bei Fehlern gilt: SISO - Shit in, shit out ... ;-)

        cu,
        Andreas a/k/a MudGuard

        1. Hallo,

          Und bei Fehlern gilt: SISO - Shit in, shit out ... ;-)

          der sogenannte Flush-Speicher.

          Gruß
          Kalk