Как я могу сопоставить эту массивную нотацию, используя регулярные выражения в PHP? - PullRequest
0 голосов
/ 06 января 2019

Я пытаюсь сопоставить следующий шаблон массива с регулярным выражением:

foo[bar][baz][bim]

У меня почти есть это со следующим регулярным выражением:

~([^[]+)(?:\[(.+?)\])*~gm

Однако группы захвата включают только:

Full match: foo[bar][baz][bim]
Group 1: foo
Group 2: bim

Я не могу понять, почему он захватывает только последнее вхождение структуры []. Я бы хотел, чтобы в этом случае он захватывал foo, bar, baz и bim.

Есть идеи о том, что мне не хватает?

Ответы [ 2 ]

0 голосов
/ 06 января 2019

Это также может быть проанализировано без регулярного выражения.
Снимите закрывающий ], а затем взорвитесь на открывшемся [.

$str = "foo[bar][baz][bim]";

$str = str_replace("]","",$str);
$arr = explode("[", $str);
var_dump($arr);

Возвращает:

array(4) {
  [0]=>
  string(3) "foo"
  [1]=>
  string(3) "bar"
  [2]=>
  string(3) "baz"
  [3]=>
  string(3) "bim"
}

Где первый элемент - это имя массива, а следующий - дочерние / путь.

0 голосов
/ 06 января 2019

Повторные группы захвата в PCRE не запоминают значения каждого предыдущего шаблона. Для этого вам нужно вызвать \G токен:

(?|(\w+)|\G(?!\A)\[([^][]*)\])

Смотрите демо здесь

Распределение регулярных выражений:

  • (?| Начало группы сброса ветви
    • (\w+) Захватить символы слова
    • | или
    • \G(?!\A) Продолжение с того места, где заканчивается предыдущий матч
    • \[ Соответствует открывающей скобке
    • ([^][]*) Захватите любую вещь, кроме [ и ]
    • \] Соответствует закрывающей скобке
  • ) Конец кластера

PHP код:

preg_match_all('~(?|(\w+)|\G(?!\A)\[([^][]*)\])~', 'foo[bar][baz][bim]', $matches);
print_r($matches[1]);
...