muenzchen: preg_match_all findet nicht alles

Hallo,

[LIST]
[*]a[/*]
[*]b[/*]
[LIST]
[*]d[/*]
[*]e[/*]
[*]f[/*]
[/LIST]
[*]c[/*]
[/LIST]

Auf diese Zeichenkette wende ich dieses Suchmuster an:

preg_match_all("~[LIST](.*?)[/LIST]~i", $replacetext, $allLists, PREG_PATTERN_ORDER);

Gebe ich jetzt count(allLists[0]) aus, bekomme ich als Ergebnis immer nur 1, es werden also nicht beide Treffer gefunden. Was ist hier falsch, ich komme da echt nicht mehr weiter.

MfG, muenzchen

  1. Moin!

    Hallo,

    [LIST]
    [*]a[/*]
    [*]b[/*]
    [LIST]
    [*]d[/*]
    [*]e[/*]
    [*]f[/*]
    [/LIST]
    [*]c[/*]
    [/LIST]

    ~[LIST](.*?)[/LIST]~i

    Du suchst ein [LIST], dem beliebig viele, aber möglichst wenige Zeichen folgen, gefolgt von [/LIST].

    In deinem Text gibts dieses genau EIN Mal - nämlich in der Mitte um die Punkte d, e, und f herum.

    Deine äußere Liste wird nicht gefunden, weil beginnend vom ersten [LIST] eben nur zwei Buchstabenpunkte kommen, dann aber kein [/LIST]. Im Widerspruch zur Forderung "Möglichst wenig Zeichen dazwischen" möchtest du aber gerne "möglichst alle Zeichen dazwischen" gefunden haben bis zum letzten [/LIST].

    Dies funktioniert aber schon deshalb nicht, weil reguläre Ausdrücke keine verschachtelten Konstrukte auseinandernehmen können. Du findest derzeit einen Block in der Mitte. Über diesen Block übergreifende, nach deiner Ansicht weiterer Suchergebnisse kann es aber nicht geben.

    Reguläre Ausdrücke sind kein adäquates Mittel, um komplexe Datenstrukturen zu parsen. Dazu benötigst du einen vernünftigen Parser. Konkret: Wenn du den inneren Block gefunden hast, kannst du ihn durch einen Leerstring ersetzen und würdest erneut einen Block (den äußeren) finden können. Dies erfordert aber eben mehr, als nur einen regulären Ausdruck, es erfordert Programmlogik.

    - Sven Rautenberg

    1. Hallo,

      Hm, das ist einleuchtend. Dann werde ich mir etwas anderes überlegen müssen.
      Danke für die Erklärung.

      MfG, muenzchen

      1. Hallo,

        Hm, das ist einleuchtend. Dann werde ich mir etwas anderes überlegen müssen.

        Eventuell solltest Du Deine Überlegungen auch auf das Folgende ausdehnen:
        Dein String sieht wie irgendeine Markup-Language aus. Kannst Du nicht eine Markup-Language verwenden, für die es schon durchgestylte Parser gibt? XML z.B.

        viele Grüße

        Axel

        1. Hallo,

          Dein String sieht wie irgendeine Markup-Language aus.

          Es ist BBCode.

          Kannst Du nicht eine Markup-Language verwenden, für die es schon durchgestylte Parser gibt? XML z.B.

          Leider nicht. Es gibt zwar einige Klassen dazu, aber ich möchte die Probleme eben gerne selbst lösen, so kann ich am meisten dazu lernen.

          MfG, muenzchen