Регулярное выражение PHP / PCRE начинается с рекурсивного шаблона - PullRequest
1 голос
/ 04 марта 2020

Я пытаюсь сопоставить теги уценки с рекурсивным.

Синтаксис ввода

(TYPE: VALUE ATTR_KEY: ATTR_VALUE)

Обратите внимание, что синтаксис должен начинаться с: [a-z0-9_-]+:

Примеры входных данных:

(image: sky.jpg)
(image: sky.jpg caption: Sky (Issue This) View)
(link: https://stackoverflow.com text: Stack Overflow)
(link: https://stackoverflow.com text: Stack Overflow rel=nofollow)
(video: http://www.youtube.com/watch?v=49Kh1mS4Fhs)

В настоящее время используется следующее регулярное выражение:

(?=[^\]])\([a-z0-9_-]+:.*?\)

Но проблема возникла здесь, потому что совпадение с:

(image: sky.jpg caption: Sky (Issue This)

Ожидаемое совпадение:

(image: sky.jpg caption: Sky (Issue This) View)

Если в скобках снова используются скобки, это не совсем точно.

Я попытался использовать рекурсивные шаблоны и работает, но мне нужно ограничить запуск с символами.

(?s)\((?:[^()]+|(?R))*+\)
\((?:[^)(]+|(?R))*+\)

1 Ответ

2 голосов
/ 04 марта 2020

Вы должны использовать положительный прогноз, чтобы убедиться, что совпадение начинается с этого шаблона, но вам придется обернуть весь шаблон соответствия круглых скобок в другую группу захвата и использовать подпрограмму (?1) вместо (?R) только для повторения этого шаблона, а не для всего регулярного выражения:

(?=\([a-z0-9_-]+:)(\((?:[^()]+|(?1))*+\))
^^^^^^^^^^^^^^^^^^^            ^^^^     ^

См. Демонстрационную версию regex .

Подробности

  • (?=\([a-z0-9_-]+:) - положительный прогноз, требующий (, 1+ строчных букв ASCII, цифр, подчеркиваний или дефисов с последующим : сразу справа от текущего местоположения
  • (\((?:[^()]+|(?1))*+\)) - Захват группы 1 (будет повторен позже):
    • \( - (
    • (?:[^()]+|(?1))*+ - 1+ повторений 1+ любых символов, кроме ( и ) или весь шаблон группы 1 (рекурсивно)
    • \) - )

Если вы хотите также поддерживать смайлики , вы можете добавить их указанные c шаблоны в группу альтернатив, где regex subro utine находится в качестве первой альтернативы:

(?=\([a-z0-9_-]+:)(\((?::[)(]|[^()]|(?1))*+\))
                        ^^^^^  

Я добавляю :[)(], который соответствует :) или :( и удаляет + после [^()], чтобы иметь возможность проверить строку внутри вложенных скобок символ за символом.

Не стесняйтесь настроить его под свои нужды или добавьте больше шаблонов смайликов .

См. это регулярное выражение demo с (?=\([a-z0-9_-]+:)(\((?::(?:[()pPDd*oO]|'\()|<3|;\)|[^()]|(?1))*+\)) регулярным выражением.

...