Можно получить все содержимое в вложенных фигурных скобках из строки? Например:
Быстрая коричневая лиса прыгает через ленивую собаку
- Как найти индекс регулярного выражения в строке?
- Регулярное выражение регулярного выражения для проверки ввода: два слова с пробелом между
- Получить подстроку между двумя символами в javascript
- Регулярное выражение для разбора JSON
- Поместите URL-адреса из строки в массив с помощью regex (проблема с периодом ожидания)
Мне нужно:
Лучше в этой последовательности, от большинства вложенных.
Регулярное выражение ниже позволит вам захватить содержимое всех вложенных фигурных скобок. Обратите внимание, что это предполагает, что вложенные фигурные скобки сбалансированы; в противном случае трудно определить, какой должен быть ответ.
(?=\{((?:[^{}]++|\{(?1)\})++)\})
Результатом будет захват группы 1.
DEMO
Обратите внимание, что порядок не задан в вопросе. Распечатанный заказ определяется порядком появления открывающей фигурной скобки {
, что означает, что сначала будет напечатано содержимое самой внешней пары.
Игнорирование положительного внешнего вида с нулевой шириной (?=pattern)
на данный момент, и давайте сосредоточимся на шаблоне внутри, который:
\{((?:[^{}]++|\{(?1)\})++)\}
Часть между двумя буквальными фигурными фигурными скобками – ((?:[^{}]++|\{(?1)\})++)
будет соответствовать 1 или более экземплярам:
[^{}]++
или {}
, который может содержать множество других не-фигурных скобок или других блоков. Вышеупомянутый шаблон может соответствовать тексту, который не содержит {}
, что нам не нужно. Поэтому мы убеждаемся, что совпадение представляет собой блок, заключенный {}
парой фигурных скобок {}
в 2 концах: \{((?:[^{}]++|\{(?1)\})++)\}
.
Поскольку нам нужен контент внутри всех вложенных фигурных скобок, нам нужно не допустить, чтобы движок не потреблял текст. Вот тут и появляется возможность использовать позитивный внешний вид с нулевой шириной .
Это не очень эффективно, поскольку вы будете переделывать соответствие для фигурных скобок, но я сомневаюсь, что существует какое-то другое общее решение с регулярным выражением, которое может эффективно его обрабатывать.
Обычный код может обрабатывать все эффективно за один проход, и рекомендуется, если вы собираетесь продлить свое требование в будущем.
Простое решение без регулярного выражения за один проход:
$str = 'The {quick} brown fox {jumps {over the} lazy} dog'; $result = parseCurlyBrace($str); echo '<pre>' . print_r($result,true) . '</pre>'; function parseCurlyBrace($str) { $length = strlen($str); $stack = array(); $result = array(); for($i=0; $i < $length; $i++) { if($str[$i] == '{') { $stack[] = $i; } if($str[$i] == '}') { $open = array_pop($stack); $result[] = substr($str,$open+1, $i-$open-1); } } return $result; }
Вы можете попробовать следующее:
$subject = 'The {quick} brown fox {jumps {over the} lazy} dog'; function nestor($subject) { $result = false; preg_match_all('~[^{}]+|\{(?<nested>(?R)*)\}~', $subject, $matches); foreach($matches['nested'] as $match) { if ($match != "") { $result[] = $match; $nesty = nestor($match); if ($nesty) $result = array_merge($result,$nesty); // $result[]=$nesty; // to preserve the hierarchy } } return $result; } print_r(nestor($subject));
Используемый здесь шаблон соответствует вложенной структуре, но не может захватывать с глубиной больше 1. Это причина, по которой функция nestor рекурсивно применяется в каждом матче.
Вы можете изучить другой способ с помощью этого другого шаблона с помощью модификатора \ G:
$subject = 'The {quick} brown fox {jumps {over the}{ fat} lazy} dog'; $pattern = '~[^{}]++|\G\{(?<nested>(?R)*+)\}~'; preg_match_all($pattern, $subject, $matches/*, PREG_SET_ORDER*/); print_r($matches);
Если вы посмотрите на результат, вы можете легко определить правила, чтобы знать глубину уровня каждого элемента.
Вы можете сделать это взломанным, уродливым образом следующим образом:
1) Искать все совпадения регулярного выражения {([^}]*)}
2) Найдите все совпадения регулярного выражения {([^}]*{[^}]*}[^}]*)}
(как вы можете видеть, это может быть динамически построено)
3) Найдите все совпадения регулярного выражения {([^}]*{[^}]*{[^}]*}[^}]*}[^}]*)}
… (продолжайте динамически строить его больше, пока вы не получите совпадений)
Группа захвата, обозначенная символом ()
только внутри внешней пары {}
s, позволит вам захватить только то, что находится в первой группе захвата, а не полностью совпадение регулярных выражений.