Intereting Posts
Попытка группировать ценности? Загрузка XML с помощью SimpleXML не возвращает атрибуты для некоторых элементов Защищен паролем password_verify () от чрезвычайно длинных паролей (DoS-атака)? Преобразование mysqli pagination в готовое разбиение на страницы искать все файлы и каталоги для создания эскизов в php Передача логического через PHP GET Magento добавляет настраиваемое поле в адрес доставки и платежного адреса на одной странице PHP Выбрать с помощью PDO Вызов функции-члена prepare () при ошибке, отличной от объекта Активировать расширение TwigLoader Twig в Symfony Symfony2: Как установить фильтр twig | date ("d F, Y") для вывода месяцев на шведском языке? Реализация PHP-чата на сайте участников Как удалить адреса электронной почты и номер телефона из строки в PHP? Как браузеру известно, какие файлы cookie отправляются на сервер при запросе? Двоичное дерево с использованием PHP + MySQL Количество строк в строке MySQL

Соответствие регулярных выражений вложенным начальным и конечным тегам

Вот строки, которые я хотел бы удалить из тегов {{if}} и {{\if}} , я имею в виду первый и последний (внутренние будут проверены движком):

  • "до {{if ^^ p1 ^ p2}} IN1; {{if ^ ^ p1}} {{iif}} IN3 {{/ if}} IN1-1 {{/ if}} после слова"
  • "до {{if ^ ^ p1}} IN1; {{if ^ ^ p1}} {{if ^ ^ p1}} IN3 {{/ if}} {{/ if}} IN1-1 {{/ if}} после"
  • "до {{if ^ ^ p1}} IN1; {{if ^ ^ p1}} {{if ^ ^ p1}} IN3 {{if}} {{/ if}} IN1-1 {{if ^ ^ p1 }} IN4 {{/ if}} {{/ if}} после "

Регулярное выражение: \{\{(if)\}\}(((?!\{\{\/?\1\}\})[\s\S])*(\{\{\1\}\}(?2)*\{\{\/\1\}\})*((?!\{\{\/?\1\}\})[\s\S])*)\{\{\/\1\}\}

EDIT 3: я удалил обязательство поддерживать TAG без его окончания. Я переформатировал вопрос для пользователей futur, чтобы понять некоторые комментарии ниже, см. Первую версию сообщения

Более того, у меня есть работа для всех трех одновременно, давая мне три матча, которые не работают на веб-сайте regex101. Разрыв линии должен поддерживаться в матче. Хотя, я мог бы согласиться, что только последние два в сочетании дают два матча, потому что я могу изменить тег один, if для iif .

Мое другое решение не использует регулярные выражения, но я хотел бы сделать это, если это возможно.

Вы можете использовать

 ~{{ # Opening tag start (\w+) # (Group 1) Tag name \^ # Aux delimiter ([^^\{\}]?) # (Group 2) Specific delimiter \^ # Aux delimiter ([^\{\}]+) # (Group 3) Parameters }} # Opening tag end ( # (Group 4) (?> (?R) # Repeat the whole pattern | # or match all that is not the opening/closing tag [^{]*(?:\{(?!{/?\1[^\{\}]*}})[^{]*)* )* # Zero or more times ) {{/\1}} # Closing tag ~ix 

См. Демо-версию regex

В общем, выражение основано на рекурсии и умеренном жадном токене . Часть [^{]*(?:\{(?!{/?\1[^\{\}]*}})[^{]*)* является развернутой (?s:(?!{{/?\1}}).)* {{TAG}} ) . )*, который соответствует любому символу ( . ), (?s:(?!{{/?\1}}).)* не является отправной точкой для последовательностей символов {{TAG}} или {{/TAG}} .

Вам не нужен модификатор DOTALL для этого шаблона, поскольку его нет . в шаблоне.

Вот демо-версия PHP :

 $re = '~{{(\w+)\^([^^\{\}]?)\^([^\{\}]+)}}((?>(?R)|[^{]*(?:\{(?!{/?\1[^\{\}]*}})[^{]*)*)*){{/\1}}~i'; $str = "before {{if^^p1^p2}} IN1; {{if^ ^p1}} {{iif}} IN3 {{/if}} IN1-1 {{/if}} after\nbefore {{if^ ^p1}} IN1; {{if^ ^p1}} {{if^ ^p1}} IN3 {{/if}} {{/if}} IN1-1 {{/if}} after\nbefore {{if^ ^p1}} IN1; {{if^ ^p1}} {{if^ ^p1}} IN3 {{/if}} {{/if}} IN1-1 {{if^ ^p1}} IN4 {{/if}} {{/if}} after"; preg_match_all($re, $str, $matches); print_r($matches);