относительно простой Preg_match_all вызывает 502 Bad Gateway

У меня есть функции preg_match_all с шаблоном:

preg_match_all(
'/\[(if) ([^\]]*)\]
((?:(?!\[if).|(?R))*?)
\[endif\]/sx',
$text,
$matches
);

Это довольно простой шаблон, я думаю, он ищет синтаксис [if condition] sometext [endif], но он также поддерживает встраивание ifs f.e. [if condition1] aa [if condition2] bb [endif] [endif], Я использовал переключатель s, чтобы рассматривать новые строки как точки (поскольку я хочу, чтобы они работали многострочно), а x — для более удобного чтения (но удаление x не решает проблему).

Он отлично работает для большинства входных данных, которые у меня есть, но для некоторых конкретных входных данных он вызывает ошибку 502 Bad gateway на сервере nginx без каких-либо ошибок или исключений в журналах. Я использую nginx + php-fpm (5.6.15-1 + deb.sury.org ~ trusty + 1), но то же самое происходит на php7.

Вот причина ошибки 502 Плохой шлюз PHP-кода, который вы можете легко проверить, очень просто, просто переменная и регулярное выражение.

http://pastebin.com/G54Xa0as

Пожалуйста, убедитесь, что вы скопировали контент 1: 1 со всеми пробелами, вкладками и т. Д.

Очень странно то, что вы можете удалить практически любую отдельную строку или даже удалить один отступ (несколько пробелов в любом месте), чтобы он работал.

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

2

Решение

Ваше регулярное выражение содержит негативную перспективу, которая «смягчает» шаблон точек. Однако вы не смогли добавить к нему конечный разделитель, и он стал довольно «тяжелым».

Я предлагаю добавить конечный разделитель ([endif]) к проверке:

\[(if)\s+([^\]]*+)\]((?>(?!\[(?:end)?if\b).|(?R))*)\[endif\]
^^^^^^^^

Увидеть демонстрация

Или вы можете даже развернуть закаленный жадный жетон как

\[(if)\s+([^\]]*+)\]((?>[^[]++(?:\[(?!(?:end)?if\b)[^[]*)*|(?R))*)\[endif\]

Увидеть регулярное выражение демо (однако, если [ может следовать [if...]это не сработает)

Также, нота что у вашего регулярного выражения есть пробел после (if) и так как вы используете /x Модификатор, он не считается буквальным пространством, но игнорируется. Вот почему я изменил его на \s+,

2

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]