【问题标题】:WordPress: Problem with the shortcode regexWordPress:简码正则表达式的问题
【发布时间】:2011-02-03 14:01:51
【问题描述】:

这是用于 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 /]

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

[foo bar="[baz /]"]content[/foo]

因为正则表达式会在第一次出现右括号时停止主简码,所以在示例中它呈现

[foo bar="[baz /]

"]content[/foo]

按原样显示。

是否有任何方法可以更改正则表达式,使其绕过任何出现的 [] 及其在开始标记或自闭标记之间出现的内容?

【问题讨论】:

标签: php regex wordpress


【解决方案1】:

你的目标是什么?即使 WordPress 的正则表达式更好,也不会执行短代码。

【讨论】:

    【解决方案2】:
    return '(.?)\[('.$tagregexp.')\b((?:"[^"]*"|.)*?)(?:/)?\](?:(.+?)\[\/\2\])?(.?)';
    

    是第一个正则表达式的变体,其中匹配属性的位已更改为完全捕获字符串而不考虑其中的内容:

    (?:"[^"]*"|.)*?
    

    而不是

    .*?
    

    请注意,它不处理其中包含转义引号字符的字符串(但是 - 可以这样做,但有必要吗?)。我没有更改任何其他内容,因为我不知道 WordPress 短代码的语法。

    但看起来它可以通过删除不必要的反斜杠和括号来稍微清理一下:

    return '(.?)\[(foo)\b((?:"[^"]*"|.)*?)/?\](?:(.+?)\[/\2\])?(.?)';
    

    也许需要进一步改进。我有点担心上面 sn-p 中不精确的点,我宁愿使用(?:"[^"]*"|[^/\]])* 而不是(?:"[^"]*"|.)*?,但我不知道这是否会破坏其他东西。另外,我不知道(.?) 的前导和尾随有什么好处。它们与您的示例中的任何内容都不匹配,因此我不知道它们的目的。

    【讨论】:

      【解决方案3】:

      您想要替换该正则表达式吗?这一个允许属性值包含看起来像标签的东西,如您的示例中所示:

      '(.?)\[(\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 这样的应用程序。添加或更改功能的唯一方法是使正则表达式变得更大、更难看,甚至更难维护。

      【讨论】:

      • 我尝试替换整个正则表达式,并且短代码显示为文本。我尝试仅使用第 3 组和正常的简码运行,但是当简码中有简码时,只有里面的简码运行,而周围的简码显示为文本。
      【解决方案4】:

      我找到了解决方法: 首先,将简码正则表达式从:

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

      收件人:

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

      然后更改 do_shortcode 函数的优先级以避免与 wptexturize 冲突,wptexturize 是样式化引号并搞砸此修复的函数。 wpautop 没有问题,因为我认为最近的另一个功能已经解决了这个问题。

      之前:

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

      之后:

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

      我将此提交给了 trac,并且处于某种永久中断状态。与此同时,我想如果我可以制作一个插件来应用我的修复而不更改核心文件。覆盖过滤器优先级很容易,但我不知道如何覆盖正则表达式。

      【讨论】:

        【解决方案5】:

        这会很好解决!我没有足够的代表发表评论,所以我留下以下相关的 wordpress trac 链接,也许它与您的意思相同: http://core.trac.wordpress.org/ticket/14481

        我希望任何修复都允许类似的短代码语法

        [shortcode att1="val]ue"]content[/shortcode]

        由于在 3.0.1 中 $content 被错误解析为 ue"]content 而不仅仅是 content

        更新:在花时间学习了 regices(正则表达式?)之后,我可以允许 ] 和 Pascal 风格的转义引号(例如 arg='that''s [so] great')在这些参数中进行 2 处更改:首先将第一个正则表达式 (get_shortcode_regex) 中的 (.*?) 组更改为

        ((?:[^'"\]]|'[^']*'|"[^"]*")*)

        (注意:确保您在 php 代码中正确转义所有内容)然后在 shortcode_parse_atts(包含第二个正则表达式的函数)中更改以下内容(再次,如果您单引号 @ 将 ' 更改为 \' 987654329@ 和原代码一样)

        在 $pattern 中将 "([^"]*)" 更改为 "((?:[^"]|"")*)" 在 $pattern 中将 '([^']*)' 更改为 '((?:[^']|'')*)' $atts[strtolower($m[1])] = preg_replace('_""_', '"', stripcslashes($m[2])); $atts[strtolower($m[3])] = preg_replace("_''_", "'", stripcslashes($m[4]));

        再次注意:对模式的更改可能依赖于匹配的贪婪性质,因此如果该选项发生更改,$pattern 的更改位可能必须以(?!") 之类的方式终止,等等

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2011-05-13
          • 2011-04-30
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多