У меня есть файл, который структурирован в большой многомерной структуре, похожей на json, но недостаточно закрытой для использования библиотеки json.
Данные выглядят примерно так:
alpha { beta { charlie; } delta; } echo; foxtrot { golf; hotel; } Регулярное выражение, которое я пытаюсь построить (для preg_match_all), должно совпадать с каждым родителем верхнего уровня (с разделителями {}), чтобы я мог рекурсивно проходить через совпадения, создавая многомерный php-массив, который представляет данные.
  Первое regex, которое я пробовал, это /(?<=\{).*(?=\})/s который жадно соответствует содержимому внутри фигурных скобок, однако это не совсем так, как если на верхнем уровне более одного брата матч слишком жадный.  Пример: 
  Использование regex /(?<=\{).*(?=\})/s match дается как: 
Матч 1:
  beta { charlie; } delta; } echo; foxtrot { golf; hotel; 
Вместо этого результат должен быть: Матч 1:
  beta { charlie; } delta; 
Матч 2:
  golf; hotel; 
Итак, мастера регулярных выражений, какую функцию я пропускаю здесь или мне нужно решить это с помощью php? Любые советы очень приветствуются 🙂
Вы не можете делать это с помощью регулярных выражений.
  Кроме того, если вы хотите сопоставить глубокие-мелкие блоки, вы можете использовать \{[^\{\}]*?\} И preg_replace_callback() чтобы сохранить это значение, и вернуть значение null чтобы удалить его из строки.  Обратный вызов должен будет позаботиться о вложении значения соответствующим образом. 
 $heirarchalStorage = ...; do { $string = \preg_replace_callback('#\{[^\{\}]*?\}#', function($block) use(&$heirarchalStorage) { // do your magic with $heirarchalStorage // in here return null; }, $string); } while (!empty($string)); 
Неполные, не проверенные и не гарантированные.
  Этот подход требует, чтобы строка была завершена в {} , иначе финальное совпадение не произойдет, и вы будете навечно зацикливаться. 
Это очень много ( неэффективная ) работа для чего-то, что можно так же легко решить с помощью хорошо известного формата обмена / хранения, такого как JSON.
  Я собирался поставить « можно, но … », однако я просто скажу еще раз: « Ты не можешь » 2 
2 Не делайте
Конечно, вы можете делать это с помощью регулярных выражений.
 preg_match_all( '/([^\s]+)\s*{((?:[^{}]*|(?R))*)}/', $yourStuff, $matches, PREG_SET_ORDER ); 
Это дает мне следующие в матчах:
 [1]=> string(5) "alpha" [2]=> string(46) " beta { charlie; } delta; " 
а также
 [1]=> string(7) "foxtrot" [2]=> string(22) " golf; hotel; " 
Немного сломал.
 ([^\s]+) # non-whitespace (block name) \s* # whitespace (between name and block) { # literal brace ( # begin capture (?: # don't create another capture set [^{}]* # everything not a brace |(?R) # OR recurse )* # none or more times ) # end capture } # literal brace 
Только для вашей информации это отлично работает на n-глубоких уровнях фигурных скобок.
  Я думаю, что вы можете получить что-то, используя preg_split , сопоставив [a-zA-Z0-9][:blank]+{ и } .  Вы сможете построить свой массив, пройдя результат.  Используйте рекурсивную функцию, которая идет глубже, когда вы сопоставляете открывающий тег, а верхний – с закрывающим тегом. 
В противном случае самым чистым решением будет реализация грамматики ANTLR !