【问题标题】:Regexp, skip nested pairs正则表达式,跳过嵌套对
【发布时间】:2011-03-28 10:51:15
【问题描述】:

在我自己的标记语言中,我有一个引号标签>>which use these characters to make a blockquote<<。当有嵌套的块引用时,问题就开始了:

>>(1)
start1
  >>(2)quote 2!<<(3)
<<(4)

我想只匹配最外面的标签,像这样:

<blockquote>
start1
  >>quote 2!<<
</blockquote>

如果我尝试一个简单的不贪婪的正则表达式/&gt;&gt;(.+?)&lt;&lt;/,(1) 和 (3) 将被匹配,而 (2) 和 (4) 将永远不会匹配。如果我让它变得不贪心/&gt;&gt;(.+)&gt;&gt;/ (1) 和 (4) 将成功匹配(通过递归调用该函数,我可以将 (2) 与 (3) 匹配),但是当我有两个块时它将不起作用在同一段文字中:

>>(A)quote1<<(B)

>>(C)quote2<<(D)

贪婪的人会将 (A) 与 (D) 匹配,留下 (B) 和 (C)。我想我必须以某种方式使它“不贪婪,但前提是里面没有其他对”,这超出了我的技能。有没有办法让它正常工作?那么(1)匹配(4),(A)匹配(B)和(C)匹配(D)?如果您能想到非正则表达式解决方案(但不是解析器),那么它对我来说也足够了。我不是在问如何使(2)匹配(3),只是如何成功地跳过它们(或任何其他嵌套对)。

成功!受Arjen建议的启发,最后我使用了这样的构造(不一定有效:

$text = str_replace('([^>]|^)>([^>]|$)', '$1&gt;$2', $text);
while ($len != strlen($text)){
    $len = strlen($text);
    $text = preg_replace_callback('/>>([^>]+?)<</', "blockHashFunction", $text);
}

即。我首先对所有单个 > 进行编码,然后执行递归 preg_replace。在这种情况下,散列意味着 &gt;&gt;asdsad&lt;&lt; 被替换为,例如 "\xFE:3:\xFE",在脚本的末尾,它未散列(好吧,实际上更像是解码,我猜)到正确的 &lt;blockquote&gt;asdsad&lt;/blockquote&gt;

【问题讨论】:

  • 单个正则表达式应用程序无法处理嵌套项。

标签: regex


【解决方案1】:

正则表达式并不适合这种解析。实际上有一些 RegEx 引擎确实支持嵌套/平衡匹配,例如 .NET Framework RegEx 引擎(请参阅:http://blogs.msdn.com/b/bclteam/archive/2005/03/15/396452.aspx)。但是,我觉得这会导致非常复杂的模式。

如果您创建一个匹配开始或结束标记的正则表达式并手动创建所有匹配项的树,则效果会更好。处理完整个字符串后,您可以从结果集合中丢弃不需要的匹配项。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-05
    • 2011-07-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多