В настоящее время я создаю механизм синтаксического анализа bbcode, и я столкнулся с ситуацией, которую я не могу понять самостоятельно.
Дело в том, что я столкнулся с проблемой, подобной этой:
Apache / PHP в Windows падает с регулярным выражением
Это означает, что если я сделаю что-то похожее на приведенный ниже пример, Apache аварийно завершит работу из-за того, что число рекурсий достигло 690 (ограничение памяти 1 МБ для PCRE):
$txt = '[b]'.str_repeat('a', 338).'[/b]'; // if I change repeat count to lower value it's ok
$regex = '#\[(?P<attributes>(?P<tag>[a-z0-9_]*?)(?:=.*?|\s.*?|))](?P<content>(?:[^[]|\[(?!/?(?P=tag)])|(?R))+?)\[/(?P=tag)]#mi';
echo preg_replace_callback($regex, function($matches) { return $matches['content']; }, $txt);
Так что мне нужно каким-то образом минимизировать потребность в *
и +
в моем регулярном выражении, но здесь у меня нет идей, поэтому я подумал, что, может быть, вы могли бы что-то предложить.
Другие подходы для парсинга bbcode (которые могут обрабатывать вложенные теги) приветствуются.
Однако я не хотел бы использовать уже построенный класс или что-то. Мне нравится делать вещи самостоятельно!
Я также изучил PECL и Pear HTML_BBCodeParser. Но я не хочу, чтобы мое приложение зависело от расширений. Скорее всего, я могу сделать какой-нибудь скрипт, который проверяет это расширение и, если он не существует, использовать парсер BBCode, который я пытаюсь сделать здесь.
Извините, если мои описания мрачны, я не профессионал в английском ^^
EDIT. Итак, регулярное выражение объяснило:
\[(?P<attributes>(?P<tag>[a-z0-9_]*?)(?:=.*?|\s.*?|))]
Это мой начальный тег. Я использовал именованные группы. С помощью «тега» я идентифицирую тег, а с «атрибутами» - атрибуты тегов. Думайте о теге как об атрибуте. Так что здесь происходит? Я пытаюсь сопоставить тег, когда сопоставляется тег, я пытаюсь сопоставить что-либо после знака =
или что-нибудь после \s
(пробел), пока не достигнет закрытия тега ]
.
(?P<content>(?:[^[]|\[(?!/?(?P=tag)])|(?R))+?)
Теперь я пытаюсь сопоставить содержимое. Это сложная часть. Я ищу любой символ, которого нет [и если я его найду, то я проверяю, не является ли он моим конечным тегом или рекурсией, и говорю движку регулярных выражений делать это до тех пор, пока ....
\[/(?P=tag)]
... найден конечный тег.