Achim Schrepfer: Mal wieder ein RegEx-Problem

Hallo liebe RegEx-Freunde,

jeder kennt das: man möchte in einem Eingabeformular z.B. für ein Forum rudimentäre Formatierungsmöglichkeiten erlauben, aber nicht gleich die Eingabe als HTML ermöglichen. Also, ich wollte einige selbstdefinierte Tags für z.B. Fett- und Kursivschrift und Links einbauen. So, nun hab ich mich am Forum hier orientiert und das mit eckigen Klammern gemacht:

[b:Text in fett] sollte dann also Fett gedruckt werden. Soweit so gut. Das krieg ich auch grad noch hin. Aber wenn nun in dem fetten Text eine eckige Klammer "]" stehen soll:

[b:Text mit Klammer ] in fett] dann würde nur "Text mit Klammer" fettgedruckt werden (das Muster ist nongreedy. Das wäre also folgender Ausdruck:
/[([bi]):(.*?)]/

Wie kann ich es erreichen, daß [b:Text mit Klammer ] in fett] komplett gematcht wird? Man soll die eckigen Klammern also mit einem Slash "" quoten können.

viele Grüße und vielen Dank für Eure Hilfe
Achim Schrepfer

  1. Hallo Achim,

    /[([bi]):(.*?)]/

    Besser waere:

    /[([bi]):([^]]*)]/

    Wie kann ich es erreichen, daß [b:Text mit Klammer ] in
    fett] komplett gematcht wird? Man soll die eckigen Klammern
    also mit einem Slash "" quoten können.

    Hm. Da muss (leider) der ?-Operator her:

    /[([bi]):(.*?[^\])]/

    Gruesse,
     CK

    1. Hi Christian,

      Besser waere:
      /[([bi]):([^]]*)]/

      klar...

      Wie kann ich es erreichen, daß [b:Text mit Klammer ] in
      fett] komplett gematcht wird? Man soll die eckigen Klammern
      also mit einem Slash "" quoten können.
      Hm. Da muss (leider) der ?-Operator her:

      /[([bi]):(.*?[^\])]/

      Das kann aber nicht funktionieren. In PHP zumindest scheint der zweite Slash bei [^\] die eckige Klammer zu quoten. Fehler: missing terminating ] for character class at offset 20

      Vorhin hatte ich das schon mit drei Slashes. Das geht schonmal, aber dann habe ich im Text immer noch die "]" übrig. Ich könnte noch eine Substitution machen und alle "]" in ] umsetzen. Dann ergibt sich aber das Problem, wenn man die Zeichenfolge "]" tatsächlich im Text haben will, müsste man "\\]" oder so schreiben.

      Mein Problem ist also eher allgemeiner Natur. Vielleicht muss ich ja einen grösseren Aufwand betreiben, aber ich habe keine Grundlage, wie so etwas gemacht werden kann.

      viele Grüße
      Achim Schrepfer

      1. Hallo Achim,

        /[([bi]):(.*?[^\])]/

        Das kann aber nicht funktionieren.

        Es kann :)

        In PHP zumindest scheint der zweite Slash bei [^\] die
        eckige Klammer zu quoten. Fehler: missing terminating ]
        for character class at offset 20

        Da bist du dem typischen PHP-Programmierer-Fehler
        aufgesessen. Du uebergibst der RegEx-Engine einen String,
        also musst du escapen:

        preg_replace("/\[([bi]):(.*?[^\\])\]/",....);

        Vorhin hatte ich das schon mit drei Slashes. Das geht
        schonmal, aber dann habe ich im Text immer noch die "]"
        übrig. Ich könnte noch eine Substitution machen und alle
        "]" in ] umsetzen.

        Dafuer gibt es den e-Flag. Du musst halt den String, den du
        im Ersetzungsteil bekommst, per str_replace() oder so
        saeubern, z. B. so:

        preg_replace("/\[([bi]):(.*?[^\\])\]/e","str_replace($1,'\]',']');",$txt);

        kann sein, dass du das $1 noch in '' schreiben musst.

        Gruesse,
         CK

        1. Hi CK,

          /[([bi]):(.*?[^\])]/
          Das kann aber nicht funktionieren.
          Es kann :)

          Da bist du dem typischen PHP-Programmierer-Fehler
          aufgesessen. Du uebergibst der RegEx-Engine einen String,
          also musst du escapen:
          preg_replace("/\[([bi]):(.*?[^\\])\]/",....);

          *g* ich übergebe Strings meistens in Single-Quotes, damit ich mir sowas erspare.

          Dafuer gibt es den e-Flag. Du musst halt den String, den du
          im Ersetzungsteil bekommst, per str_replace() oder so
          saeubern, z. B. so:
            preg_replace("/\[([bi]):(.*?[^\\])\]/e","str_replace($1,'\]',']');",$txt);

          das e-Flag! Das war der Durchbruch! Obwohl es bei mir jetzt so aussieht:
          preg_replace('/[([bi]):(.*?[^\])]/e','"<\1>".str_replace("]","]","\2")."</\1>"',$text);

          Ach ja, die double quotes hab ich grad durch single quotes ersetzt, weil sonst würden in "\2" Variablennamen expandiert werden und das will ich natürlich auch nicht *g*.

          kann sein, dass du das $1 noch in '' schreiben musst.

          $1 wäre im Zweifel $2 und der "haystack" steht bei preg_replace als drittes Argument. Das hat mich zunächst ganz schön verwirrt, Christian! ;-)

          Auf jeden Fall scheint es jetzt zu funktionieren. Danke nochmal und frohe Weihnachten.

          viele Grüße
          Achim Schrepfer

          1. Hallo Achim,

            kann sein, dass du das $1 noch in '' schreiben musst.

            $1 wäre im Zweifel $2

            Ups :) Da hast du recht.

            und der "haystack" steht bei preg_replace als drittes
            Argument.

            Hoe?

            string preg_replace(string pattern,string replace,string text)

            Gruesse,
             CK

            1. Hi Christian,

              string preg_replace(string pattern,string replace,string text)

              "str_replace($1,'\]',']');" hast Du vorhin geschrieben und der Text wäre dann "]" ;)

              viele Grüße
              Achim Schrepfer

              1. Hallo Achim,

                "str_replace($1,'\]',']');" hast Du vorhin geschrieben und
                der Text wäre dann "]" ;)

                Ach so -- jetzt hast *du* mich verwirrt *g* du hast von
                preg_replace geschrieben, meintest aber str_replace *g*

                Gruesse,
                 CK

                1. Hi,

                  Ach so -- jetzt hast *du* mich verwirrt *g* du hast von
                  preg_replace geschrieben, meintest aber str_replace *g*

                  oh, sorry - hab ich mich versehentlich für die Verwirrung revanchiert, hehe ;-]

                  viele Grüße
                  Achim Schrepfer