正则表达式:懒惰更糟吗?

时间:2008-12-14 18:36:09

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

我总是写这样的正则表达式

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

但我刚刚了解了这个lazy thing并且我可以像这样写

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

使用第二种方法有什么不利之处吗?正则表达式肯定更紧凑(即使SO更好地解析它)。

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

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

6 个答案:

答案 0 :(得分:12)

另一件需要考虑的事情是目标文本的持续时间,以及量化的子表达式将匹配多少。例如,如果您尝试匹配整个&lt; BODY&gt;在大型HTML文档中,您可能会想要使用此正则表达式:

/<BODY>.*?<\/BODY>/is

但这会做很多不必要的工作,一次匹配一个角色,同时在每个角色之前有效地做一个负面的预测。你知道&lt; / BODY&gt;标签将非常接近文档的末尾,因此聪明的做法是使用正常的贪心量词;让它覆盖整个文档的其余部分,然后回溯匹配结束标记所需的几个字符。

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

答案 1 :(得分:8)

补充的字符类更严格地定义了您想要匹配的内容,所以无论何时,我都会使用它。

非贪婪的正则表达式将匹配您可能不想要的内容,例如:

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

你的第一个。*?匹配

foo" NAME="foo

答案 2 :(得分:7)

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

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

答案 3 :(得分:3)

这不是更好或更糟。我最常见的术语是贪婪与非贪婪,但是你把它们做了两件不同的事情。您想使用正确的任务。即当您不想在一行中捕获多个匹配项时,请关闭贪婪选项。

答案 4 :(得分:1)

“懒惰”这里是错误的词。你的意思是非贪婪而不是贪婪。我知道,使用它没有任何不利之处。但在你的特殊情况下,它也不应该更多效率。

答案 5 :(得分:1)

非贪婪更好,不是吗?它向前工作,每次检查匹配并在找到匹配时停止,而正常的kleene闭包(*)向后匹配输入的其余部分并移除东西直到找到匹配。

最后,他们做了不同的事情,但我认为非贪婪的表现优于贪婪。请记住,我没有测试过这个,但现在我很好奇。