Это регулярное выражение, используемое для «коротких кодов» в WordPress (одно для всего тега, другое для атрибутов).
return '(.?)\[('.$tagregexp.')\b(.*?)(?:(\/))?\](?:(.+?)\[\/\2\])?(.?)'; $pattern = '/(\w+)\s*=\s*"([^"]*)"(?:\s|$)|(\w+)\s*=\s*\'([^\']*)\'(?:\s|$)|(\w+)\s*=\s*([^\s\'"]+)(?:\s|$)|"([^"]*)"(?:\s|$)|(\S+)(?:\s|$)/';
Он разбирает такие вещи, как
[foo bar="baz"]content[/foo]
или
[foo /]
В Trap WordPress они говорят, что это немного некорректно, но моя главная проблема заключается в том, что он не поддерживает короткие коды внутри атрибутов, например, в
[foo bar="[baz /]"]content[/foo]
потому что регулярное выражение останавливает основной код короткого замыкания при первом появлении закрывающей скобки, поэтому в примере он отображает
[foo bar="[baz /]
а также
"]content[/foo]
показывает, как есть.
Есть ли способ изменить регулярное выражение, чтобы он обходил любое появление [
с ]
и его содержимое, когда происходит между открывающим тегом или самозакрывающимся тегом?
Какова ваша цель? Даже если регулярное выражение WordPress было лучше, короткий код не был бы выполнен.
return '(.?)\[('.$tagregexp.')\b((?:"[^"]*"|.)*?)(?:/)?\](?:(.+?)\[\/\2\])?(.?)';
представляет собой вариацию в первом регулярном выражении, где бит, который соответствует атрибутам, был изменен, чтобы полностью фиксировать строки без учета того, что в них:
(?:"[^"]*"|.)*?
вместо
.*?
Обратите внимание, что он не обрабатывает строки с экранированными символами кавычек в них (все же – может быть сделано, но это необходимо?). Я ничего не изменил, потому что не знаю синтаксиса для коротких кодов WordPress.
Но похоже, что его можно было немного очистить, удалив ненужные обратные косые черты и круглые скобки:
return '(.?)\[(foo)\b((?:"[^"]*"|.)*?)/?\](?:(.+?)\[/\2\])?(.?)';
Возможно, необходимы дальнейшие улучшения. Меня немного беспокоит нечеткая точка в приведенном выше фрагменте, и я предпочел бы использовать (?:"[^"]*"|[^/\]])*
Вместо (?:"[^"]*"|.)*?
, но я не знаю, нарушит ли это что-то другое. Кроме того, я не знаю, для чего подходят ведущие и конечные (.?)
. Они не соответствуют чему-либо в вашем примере, поэтому я не знаю их цели.
Вы хотите замену замены для этого регулярного выражения? Это позволяет значениям атрибутов содержать те вещи, которые выглядят как теги, как в вашем примере:
'(.?)\[(\w+)\b((?:[^"\'\[\]]++|(?:"[^"]*+")|(?:\'[^\']*+\'))*+)\](?:(?<=(\/)\])|([^\[\]]*+)\[\/\2\])(.?)'
Или в более удобочитаемой форме:
/(.?) # could be [ \[(\w+)\b # tag name ((?:[^"'\[\]]++ # attributes |(?:"[^"]*+") |(?:'[^']*+') )*+ )\] (?:(?<=(\/)\]) # '/' if self-closing |([^\[\]]*+) # ...or content \[\/\2\] # ...and closing tag )(.?) # could be ] /
Как я понимаю, $tagregexp
в оригинале является чередованием всех $tagregexp
тегов, которые были определены; Я заменил \w+
на читаемость. Все исходное регулярное выражение захватывает, это тоже делает и в тех же группах. Единственное различие заключается в том, что /
в самозакрывающемся теге захватывается в группе # 3 вместе с атрибутами, а также в своей собственной группе (# 4).
Я не думаю, что другое регулярное выражение нужно изменить, если вы не захотите добавить полную поддержку тегов, встроенных в значения атрибутов. Это также означало бы использование скрытых кавычек в этом, и я не знаю, как вы хотели бы это сделать. Удвоение их было бы моей догадкой; вот как это делает Textpattern, и WordPress предположительно основывается на этом.
Этот вопрос является хорошим примером того, почему приложения, такие как WordPress, не должны быть реализованы с помощью регулярных выражений. Единственный способ добавить или изменить функциональность – сделать регулярные выражения более крупными и уродливыми и еще сложнее поддерживать.
Я нашел способ исправить это: во-первых, измените регулярное выражение для короткого кода:
(.?)\[('.$tagregexp.')\b(.*?)(?:(\/))?\](?:(.+?)\[\/\2\])?(.?)
Для того, чтобы:
(.?)\[('.$tagregexp.')\b((?:[^\[\]]|(?R)|.)*?)(?:(\/))?\](?:(.+?)\[\/\2\])?(.?)
А затем измените приоритет функции do_shortcode, чтобы избежать конфликта с wptexturize, функцией, которая стилизует кавычки и испортит это исправление. У него нет проблем с wpautop, потому что это несколько исправлено с другой недавней функцией, я думаю.
До:
add_filter('the_content', 'do_shortcode', 11); // AFTER wpautop()
После:
add_filter('the_content', 'do_shortcode', 9);
Я отправил это на трассу и на какое-то постоянное перерыв. Между тем, я думаю, могу ли я сделать плагин для применения моего исправления без изменения основных файлов. Переопределить приоритет фильтра легко, но я не знаю, как переопределить регулярное выражение.
Это было бы неплохо исправить! У меня недостаточно комментариев для комментариев, поэтому я оставляю следующую связанную ссылку WordPress trac, возможно, это то же самое, что и вы: http://core.trac.wordpress.org/ticket/14481
Я надеюсь, что любое исправление позволит использовать синтаксис короткого кода, например
[shortcode att1 = "val] ue"] content [/ shortcode]
так как в 3.0.1 содержимое% неправильно анализируется как ue"]content
а не только content
Обновление : после того, как мы потратили время на изучение реестров (регулярных выражений?), Я позволил разрешить] и каскады с экранами в стиле Паскаля (например, arg = 'that' is [so] great ') в этих аргументах с двумя изменениями: сначала измените (.*?)
в первом регулярном выражении ( get_shortcode_regex
) до
((?: [^ '"\]] | '[^'] *' | "[^"] *") *)
(NB: убедитесь, что вы избегаете все правильно в своем php-коде), то в shortcode_parse_atts
(функция, содержащая второе регулярное выражение) измените следующее (опять же, измените '
на \'
если вы используете однокадровый $pattern
как в исходном коде)
в $ pattern change "([^"] *) "to" ((?: [^ "] |" ") *)" в $ pattern change '([^'] *) 'to' ((?: [^ '] |' ') *)' $ atts [strtolower ($ m [1])] = preg_replace ('_ "" _', '"', stripcslashes ($ m [2])); $ atts [strtolower ($ m [3])] = preg_replace ("_''_", "'", stripcslashes ($ m [4]));
NB снова: изменения в шаблоне могут опираться на жадный характер сопоставления, поэтому, если этот параметр когда-либо изменен, измененные биты $pattern
могут быть завершены чем-то вроде (?!")
т. Д.