【问题标题】:Regex: Is Lazy Worse?正则表达式:懒惰更糟吗?
【发布时间】:2010-09-26 21:06:40
【问题描述】:

我一直写这样的正则表达式

<A HREF="([^"]*)" TARGET="_blank">([^<]*)</A>

但我刚刚了解到lazy thing,我可以这样写

<A HREF="(.*?)" TARGET="_blank">(.*?)</A>

使用第二种方法有什么缺点吗?正则表达式肯定更紧凑(甚至 SO 也能更好地解析它)。

编辑:这里有两个最佳答案,指出了表达式之间的两个重要区别。 ysth 的回答指出了非贪婪/懒惰的弱点,其中超链接本身可能包含 A 标签的其他属性(绝对不好)。 Rob Kennedy 指出了贪婪示例中的一个弱点,即锚文本不能包含其他标签(绝对不行,因为它也不会抓取所有锚文本)......所以答案是,正则表达式就是他们是,看似相同的惰性和非惰性解决方案在语义上可能并不等效。

编辑:第三个​​最佳答案是 Alan M 关于表达式的相对速度。暂时,我会将他标记为最佳答案,以便人们给他更多积分:)

【问题讨论】:

  • 当然可以,但很明显,一旦这个问题有点老了,就没有人喜欢它了。
  • 如果您可以更改接受的答案,请随时这样做。我的回答并没有真正回答问题,只是详细说明了其他答案。
  • 我不同意。有三个方面:匹配你不想要的东西,不匹配你想要的东西,以及它将为处理器做多少工作。没有人遇到超过一个问题。
  • 哦,我应该提一下,这比我在发布问题之前所知道的多三个方面,所以这是一个很大的帮助,非常感谢你们三个!

标签: regex regex-greedy non-greedy reluctant-quantifiers


【解决方案1】:

“懒惰”在这里是错误的词。你的意思是非贪婪而不是贪婪。据我所知,使用它没有缺点。但在您的特殊情况下,它也不应该高效。

【讨论】:

  • 感谢您的回答。这些家伙regular-expressions.info/repeat.html 指的是懒惰或贪婪,我承认这比贪婪和非贪婪更有意义。
  • 您可能会感兴趣的是,“那些家伙”实际上是 SO 成员 Jan Goyvaerts。 ;)
  • 是的,我真的不能抱怨 SO memeber 的质量。上次我使用具有这种响应水平的技术论坛是 xSLT 论坛,一位名叫 David Carlile 的著名大师(类似的人)亲自回答了大部分问题。
  • Java 称它们为“不情愿”。量词是贪婪的、占有欲的或不情愿的。
【解决方案2】:

这不是更好或更坏。我见过最多的术语是贪婪与非贪婪,但无论你怎么说,它们都会做两件不同的事情。您想为任务使用正确的。 IE。当您不想在一行中捕获多个匹配项时,请关闭贪婪选项。

【讨论】:

    【解决方案3】:

    不贪婪更好,不是吗?它向前工作,每次检查匹配并在找到匹配时停止,而普通的 kleene 闭包 (*) 向后工作,匹配输入的其余部分并删除内容,直到找到匹配为止。

    最后,他们做不同的事情,但我认为非贪婪胜过贪婪。请记住,我尚未对此进行测试,但现在我很好奇。

    【讨论】:

    • 打赌它依赖于实现。感谢您的回答!
    【解决方案4】:

    请注意,您的示例并不相同。您的第一个正则表达式不会选择任何包含其他标签的链接,例如imgb。第二个正则表达式会,我希望这可能是你想要的。

    除了含义上的差异之外,我能想到的唯一缺点是对非贪婪修饰符的支持不像字符类否定那样普遍。 It's more widely supported than I thought, before I checked, but notably absent from the list is GNU Grep. 如果您使用的正则表达式评估器支持它,请继续使用它。

    【讨论】:

    • 嗨 Rob,这是真的,我确实想要任何可以在 A 标签之间移动的东西。我的正则表达式评估器是否支持它......哇,我什至不知道它不能。我必须检查一下(我在 AS3 中),然后我会用它来编辑问题。
    【解决方案5】:

    补充字符类更严格地定义了您要匹配的内容,所以只要可以,我会使用它。

    非贪婪的正则表达式会匹配你可能不想要的东西,例如:

    <A HREF="foo" NAME="foo" TARGET="_blank">foo</A>
    

    您的第一个 .* 在哪里?匹配

    foo" NAME="foo
    

    【讨论】:

    • 我不明白你的最后一句话。在您看来,这里会匹配什么,为什么会与我们想要的不同?
    • 不是第一个.*吗?在匹配双引号之前匹配尽可能少的字符,因此只匹配 foo?
    • ysth:我现在明白你的意思了,即参数已重新排序。
    • 很难说在这种情况下我想要匹配什么,因为它不是合法的 HTML(或者至少对我来说没有意义)。
    • 肯尼:不,.*?将首先尝试通过第一个双引号进行匹配,但如果这不允许成功匹配,它将继续使用第二个双引号,依此类推。
    【解决方案6】:

    要考虑的另一件事是目标文本有多长,以及量化子表达式将匹配多少。例如,如果您试图匹配大型 HTML 文档中的整个

    元素,您可能会想使用这个正则表达式:
    /<BODY>.*?<\/BODY>/is
    

    但这会做很多不必要的工作,一次匹配一个字符,同时在每个字符之前有效地进行负前瞻。您知道 标记将非常接近文档的末尾,因此明智的做法是使用正常的贪心数量;让它吞噬整个文档的其余部分,然后回溯匹配结束标记所需的几个字符。

    在大多数情况下,您不会注意到贪婪量词和不情愿量词之间的速度差异,但请记住这一点。你应该明智地使用不情愿量词的主要原因是其他人指出的:他们可能不情愿地这样做,但如果这是实现整体所需的,他们会比你想要的更多。匹配。

    【讨论】:

      猜你喜欢
      • 2012-11-30
      • 1970-01-01
      • 2012-01-26
      • 1970-01-01
      • 1970-01-01
      • 2011-03-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多