Php WordPress:短代码正则表达式有问题

Php WordPress:短代码正则表达式有问题,php,regex,wordpress,Php,Regex,Wordpress,这是WordPress中用于短代码的正则表达式,一个用于整个标记,另一个用于属性 return '(.?)\[('.$tagregexp.')\b(.*?)(?:(\/))?\](?:(.+?)\[\/\2\])?(.?)'; $pattern = '/(\w+)\s*=\s*"([^"]*)"(?:\s|$)|(\w+)\s*=\s*\'([^\']*)\'(?:\s|$)|(\w+)\s*=\s*([^\s\'"]+)(?:\s|$)|"([^"]*)"(?:\s|$)|(\S+)(?:\s

这是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]

在WordPress trac中,他们说它有点缺陷,但我的主要问题是它不支持属性中的短代码,比如

[foo bar="[baz /]"]content[/foo]
因为正则表达式在第一次出现右括号时停止主短代码,所以在示例中它呈现

[foo bar="[baz /]

照原样表演


是否有任何方法可以更改正则表达式,以便在开始标记或自动结束标记之间发生[with]及其内容时绕过任何事件?

您的目标是什么?即使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在原始版本中是所有已定义标记名的替代;我用\w+替换可读性。原始正则表达式捕获的所有内容,此正则表达式也捕获,并且在相同的组中。唯一的区别是,自动关闭标记中的/与属性一起在组3中捕获,也在其自己的组4中捕获

我认为不需要更改其他正则表达式,除非您想添加对嵌入在属性值中的标记的完全支持。这也意味着允许在这一个转义引号,我不知道你想怎么做。我猜他们会加倍;Textpattern就是这样做的,WordPress就是基于这个

这个问题是一个很好的例子,说明为什么像WordPress这样的应用程序不应该用正则表达式实现。添加或更改功能的唯一方法是使正则表达式更大、更难看,甚至更难维护。

我找到了一种解决方法: 首先,将快捷码regex更改为:

(.?)\[('.$tagregexp.')\b(.*?)(?:(\/))?\](?:(.+?)\[\/\2\])?(.?)
致:

然后更改do_shortcode函数的优先级,以避免与WPTextureSize冲突,WPTextureSize函数用于设置引号的样式并将此修复程序搞乱。它与wpautop没有问题,因为我认为这在某种程度上是通过最近的另一个函数修复的

之前:

add_filter('the_content', 'do_shortcode', 11); // AFTER wpautop() 
之后:

add_filter('the_content', 'do_shortcode', 9);  

我向trac提交了这封信,现在处于某种永久性的中断状态。与此同时,我想我是否可以制作一个插件,在不改变核心文件的情况下应用我的修复程序。覆盖过滤器优先级很容易,但我不知道如何覆盖正则表达式。

这将很好地解决!我没有足够的代表发表评论,所以我留下以下相关的wordpress trac链接,可能与您的意思相同:

我希望任何修复都能允许像这样的短代码语法

[shortcode att1=val]ue]内容[/shortcode]

因为在3.0.1中,$content被错误地解析为ue]content,而不仅仅是content

更新:花时间学习regices regex之后?我在这些参数中允许]和Pascal样式的转义引号,例如arg='thats[so]great',并做了两个更改:第一个更改。*?第一个正则表达式中的组get_shortcode_regex to


再次注意:对模式的更改可能依赖于匹配的贪婪性质,所以如果该选项发生更改,$pattern的更改位可能必须以如下方式终止:?!,etc

我们在哪里可以找到这个正则表达式?如果我们能确切地看到它是如何使用的,那会有所帮助。没关系,我找到了:我试着替换整个正则表达式,而短代码显示为文本。我只尝试了第三组和普通的短代码运行,但是当短代码中有短代码时,只有运行中的短代码和周围的短代码显示为文本。
(.?)\[('.$tagregexp.')\b((?:[^\[\]]|(?R)|.)*?)(?:(\/))?\](?:(.+?)\[\/\2\])?(.?)
add_filter('the_content', 'do_shortcode', 11); // AFTER wpautop() 
add_filter('the_content', 'do_shortcode', 9);  
((?:[^'"\]]|'[^']*'|"[^"]*")*) in $pattern change "([^"]*)" to "((?:[^"]|"")*)" in $pattern change '([^']*)' to '((?:[^']|'')*)' $atts[strtolower($m[1])] = preg_replace('_""_', '"', stripcslashes($m[2])); $atts[strtolower($m[3])] = preg_replace("_''_", "'", stripcslashes($m[4]));