Olivia A.: preg_match_all

Hallo!

ich habe einen String, der mehrere Bezeichner enthalten kann, die durch Tags in eckigen Klammern getrennt sind.

Beispiel:

Name[COMMA][SPACE]Vorname[NEWLINE]Straße[SPACE]Hausnummer[NEWLINE]Postleitzahl[SPACE]Ort[TITLE=Anschrift]

Bei den Bezeichnern sind auch Leerzeichen, Sonderzeichen etc. möglich. Die Tags können auch nicht positionsbezogen sein und Werte enthalten (TITLE), sind aber alle vordefiniert (COMMA|SPACE|NEWLINE|TITLE), damit u.U. auch eckige Klammern innerhalb der Bezeichner möglich sind.

Wie kriege ich mit preg_match_all alle Bezeichner und Tags getrennt in einer Liste?
Also:

Array([0] => Name [1] => [COMMA] [2] => [SPACE] [3] => Vorname [4] => [NEWLINE] 5 => Straße ...)

Danke,
Olivia

  1. Mahlzeit.

    Name[COMMA][SPACE]Vorname[NEWLINE]Straße[SPACE]Hausnummer[NEWLINE]Postleitzahl[SPACE]Ort[TITLE=Anschrift]

    Wie kriege ich mit preg_match_all alle Bezeichner und Tags getrennt in einer Liste?

    Array([0] => Name [1] => [COMMA] [2] => [SPACE] [3] => Vorname [4] => [NEWLINE] 5 => Straße ...)

    Das sieht eher so aus, als wenn du den Text aufteilen willst. Insofern würde ich zu preg_split greifen:

    preg_split('/([(?:COMMA|SPACE|NEWLINE|SPACE|TITLE)(?:=[^]]*)?])/', $s, 0, PREG_SPLIT_DELIM_CAPTURE);

    array(15) {
      [0]=>
      string(4) "Name"
      [1]=>
      string(7) "[COMMA]"
      [2]=>
      string(0) ""
      [3]=>
      string(7) "[SPACE]"
      [4]=>
      string(7) "Vorname"
      [5]=>
      string(9) "[NEWLINE]"
      [6]=>
      string(7) "Straße"
      [7]=>
      string(7) "[SPACE]"
      [8]=>
      string(10) "Hausnummer"
      [9]=>
      string(9) "[NEWLINE]"
      [10]=>
      string(12) "Postleitzahl"
      [11]=>
      string(7) "[SPACE]"
      [12]=>
      string(3) "Ort"
      [13]=>
      string(17) "[TITLE=Anschrift]"
      [14]=>
      string(0) ""
    }

    Die Tags … sind aber alle vordefiniert (COMMA|SPACE|NEWLINE|TITLE), damit u.U. auch eckige Klammern innerhalb der Bezeichner möglich sind.

    Vielleicht hast du dir da etwas Spezielles gedacht, aber ob Klammern innerhalb eines Datums möglich sind, hängt nicht davon ab, ob der Datumsbezeichner definiert ist, sondern ob die Klammer maskiert werden kann.

    Anders ausgedrückt: Was hilft dir die Definition von TITLE als Bezeichner bei der Entscheidung, ob [TITLE=Bla]] die Aussage "TITLE ist Bla]" meint oder "TITLE ist Bla, danach folgt der Text ]"?
    Der übliche Weg, Sonderzeichen als normale Zeichen zu erlauben, ist jedenfalls die Maskierung: [TITLE=Bla]] für "TITLE ist Bla]" und TITLE=Bla]] für "TITLE ist Bla, danach folgt der Text ]". (Obiger Vorschlag beachtet eine solche Maskierung noch nicht.)

    Gruß, Rolle

    1. Das sieht eher so aus, als wenn du den Text aufteilen willst. Insofern würde ich zu preg_split greifen:

      preg_split('/([(?:COMMA|SPACE|NEWLINE|SPACE|TITLE)(?:=[^]]*)?])/', $s, 0, PREG_SPLIT_DELIM_CAPTURE);

      Prima, vielen Dank! Wieso entstehen bei dem Ausdruck eigentlich leere Werte?

      Bei Deinem Beispiel hat das Array zwei leere Einträge und bei meinen Tests habe ich auch ständig welche.

      1. preg_split('/([(?:COMMA|SPACE|NEWLINE|SPACE|TITLE)(?:=[^]]*)?])/', $s, 0, PREG_SPLIT_DELIM_CAPTURE);

        Prima, vielen Dank! Wieso entstehen bei dem Ausdruck eigentlich leere Werte?

        Bei Deinem Beispiel hat das Array zwei leere Einträge und bei meinen Tests habe ich auch ständig welche.

        preg_split() trennt die Zeichenkette an den Stellen auf, die auf das gegebene Muster passen, wobei die Trennstellen normalerweise nicht in das Ergebnis einfließen.

        Würde "a,b,c" an den Kommata getrennt werden, kämen "a", "b" und "c" raus, die Kommata als Trenner fallen weg. Bei "a,,b" wäre das Ergbnis dementsprechend "a", "" (nichts) und "b", denn zwischen den beiden Kommata steht ja nichts.
        Das ist zugegebenermaßen etwas anders als bei der vielleicht naheliegendsten Anwendung so einer Texttrennung, der Aufzählung aller Wörter eines Satzes, wo direkt aufeinander folgende Trenner, d.h. Leerzeichen, zu einer einzelnen Leerstelle zusammengefasst werden ("zwei  Leerzeichen" -> "zwei", "Leerzeichen").

        Da preg_split() als Option noch PREG_SPLIT_DELIM_CAPTURE bekommen hat, gibt die Funktion die Trenner bzw. die in runden Klammern stehenden Teile der Trenner ebenfalls zurück (_DELIM_CAPTURE für "delimiter capture", in etwa "Trenner mitnehmen"). Als Trenner benennt das Muster, grob gesagt, die in eckigen Klammern stehenden Teile, also [COMMA], [SPACE] etc.

        In "Name[COMMA][SPACE]Vorname" finden wir nun das Gleiche wie in "a,,b": Einen Text ("Name"), einen Trenner ("[COMMA]"), Nichts (""), einen Trenner ("[SPACE]") und einen Text ("Vorname") – genau dies gibt preg_split() mit PREG_SPLIT_DELIM_CAPTURE zurück. Daher die leeren Einträge: Das sind die Stellen, an denen zwei eckige Ausdrücke direkt aufeinandertreffen.

        Stören dich die leeren Einträge, benutze PREG_SPLIT_NO_EMPTY als zusätzliche Option.

        1. In "Name[COMMA][SPACE]Vorname" finden wir nun das Gleiche wie in "a,,b": Einen Text ("Name"), einen Trenner ("[COMMA]"), Nichts (""), einen Trenner ("[SPACE]") und einen Text ("Vorname") – genau dies gibt preg_split() mit PREG_SPLIT_DELIM_CAPTURE zurück. Daher die leeren Einträge: Das sind die Stellen, an denen zwei eckige Ausdrücke direkt aufeinandertreffen.

          Stören dich die leeren Einträge, benutze PREG_SPLIT_NO_EMPTY als zusätzliche Option.

          Vielen Dank, jetzt habe ich das verstanden und mit PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY sind jetzt auch die leeren Einträge weg!