12

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

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

但是我刚刚了解到这个懒惰的东西,我可以这样写

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

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

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

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

4

6 回答 6

12

要考虑的另一件事是目标文本有多长,以及量化子表达式将匹配多少。例如,如果您尝试匹配大型 HTML 文档中的整个 <BODY> 元素,您可能会想使用这个正则表达式:

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

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

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

于 2008-12-15T01:57:52.400 回答
8

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

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

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

你的第一个.*在哪里?火柴

foo" NAME="foo
于 2008-12-14T19:51:33.030 回答
7

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

除了含义上的差异之外,我能想到的唯一缺点是对非贪婪修饰符的支持并不像字符类否定那样普遍。在我检查之前,它的支持比我想象的要广泛,但值得注意的是 GNU Grep 不在列表中。如果您使用的正则表达式评估器支持它,那么继续使用它。

于 2008-12-14T19:16:50.447 回答
3

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

于 2008-12-14T18:40:29.583 回答
1

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

于 2008-12-14T18:40:22.080 回答
1

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

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

于 2008-12-14T18:42:38.050 回答