Шаблон регулярных выражений для коротких кодов в PHP


У меня проблема с регулярным выражением, которое я написал, чтобы соответствовать коротким кодам в PHP.

Это шаблон, где $shortcode - название шорткода:

\[$shortcode(.+?)?\](?:(.+?)?\[\/$shortcode\])?

Теперь это регулярное выражение довольно хорошо работает с этими форматами:

  • [shortcode]
  • [shortcode=value]
  • [shortcode key=value]
  • [shortcode=value]Text[/shortcode]
  • [shortcode key1=value1 key2=value2]Text[shortcode]

Но, похоже, у него проблемы с наиболее распространенным форматом,

  • [shortcode]Text[/shortcode]

, который возвращает, как соответствует следующее:

Array
(
    [0] => [shortcode]Text[/shortcode]
    [1] => ]Text[/shortcode
)

Как вы можете видеть, второе совпадение (которое должно быть текстом, так как первое необязательно) включает конец открывающего тега и весь закрывающий тег, кроме последней скобки.

РЕДАКТИРОВАТЬ: Обнаружил, что возвращенное совпадение является первым захватом, а не вторым. Смотрите регулярное выражение в Регулярном выражении.

Не могли бы вы помочь с этим, пожалуйста? Я действительно ломаю себе голову над этим.

Author: Luca, 2012-07-05

2 answers

В вашем регулярном выражении:

\[$shortcode(.+?)?\](?:(.+?)?\[\/$shortcode\])?

Первая группа захвата (.+?) соответствует по крайней мере 1 символу.

Вся группа необязательна, но в данном случае она совпадает со всеми вещами до последнего ].

Работает следующее регулярное выражение:

\[$shortcode(.*?)?\](?:(.+?)?\[\/$shortcode\])?

Квантор * означает 0 или более, в то время как + означает один или несколько.

 7
Author: arnaud576875, 2012-07-05 14:38:46

Конечно, это из C#, но

@"\[([\w-_]+)([^\]]*)?\](?:(.+?)?\[\/\1\])?"

Должен соответствовать любому (?), возможно, самозакрывающемуся шорткоду.

Или вы можете украсть из wordpress: https://core.trac.wordpress.org/browser/tags/4.0/src/wp-includes/shortcodes.php#L309

$pattern = '/(\w+)\s*=\s*"([^"]*)"(?:\s|$)|(\w+)\s*=\s*\'([^\']*)\'(?:\s|$)|(\w+)\s*=\s*([^\s\'"]+)(?:\s|$)|"([^"]*)"(?:\s|$)|(\S+)(?:\s|$)/';
$text = preg_replace("/[\x{00a0}\x{200b}]+/u", " ", $text);
if ( preg_match_all($pattern, $text, $match, PREG_SET_ORDER) )...
 3
Author: drzaus, 2014-10-15 13:34:27