PCRE: найти подходящую фигурную скобку для блока кода - PullRequest
4 голосов
/ 27 февраля 2010

Есть ли способ для регулярных выражений PCRE подсчитать, сколько вхождений символа он встречает (n), и прекратить поиск после того, как он обнаружил n вхождений другого символа (в частности, { и }).

Это захват кодовых блоков (которые могут иметь или не иметь кодовые блоки, вложенные в них).

Если это упрощает, то ввод будет однострочной строкой, и единственными символами, кроме скобок, являются цифры, двоеточия и запятые. Входные данные должны соответствовать следующим критериям, прежде чем даже попытаться извлечь кодовые блоки:

$regex = '%^(\\d|\\:|\\{|\\}|,)*$%';

Все фигурные скобки будут иметь совпадающую пару и правильно вложены.

Я хотел бы знать, можно ли этого достичь, прежде чем я начну писать скрипт, чтобы проверять каждый символ в строке и подсчитывать каждое вхождение фигурной скобки. Регулярные выражения будут намного более дружественными к памяти, так как эти строки могут иметь размер несколько килобайт!

Спасибо, мниз.

Решение

PCRE: ленивый и жадный одновременно (притяжательные квантификаторы)

Ответы [ 4 ]

4 голосов
/ 27 февраля 2010

pcre имеет рекурсивные шаблоны , так что вы можете сделать что-то вроде этого

$code_is_valid = preg_match('~^({ ( (?>[^{}]+) | (?1) )* })$~x', '{' . $code .'}');

с другой стороны, я не думаю, что это будет быстрее или меньше потреблять память, чем простой счетчикособенно для больших строк.

и это как найти все (действительные) кодовые блоки в строке

preg_match_all('~ { ( (?>[^{}]+) | (?R) )* } ~x', $input, $blocks);
print_r($blocks);
4 голосов
/ 27 февраля 2010

Это именно то, для чего подходят регулярные выражения , а не . Это классический пример.

Вы должны просто перебирать строку за символом и вести подсчет уровня вложенности.

0 голосов
/ 27 февраля 2010

Это невозможно, поскольку описываемый вами язык не является обычным языком .

Вместо этого используйте парсер.

0 голосов
/ 27 февраля 2010
$regex='%^(\\d|\\:|\\{|\\}|,){0,25)$%';
preg_match($regex,$target,$matches);

где: 25 в первой строке указывает максимальное количество вхождений. затем проверьте:

$n=count($matches);
...