为什么贪婪的量词比懒惰的量词便宜
http://www.rexegg.com/regex-quantifiers.html#tempered_greed
贪婪量词 (默认) - 在缓慢减少逐个匹配的字符数量之前,通过吞咽尽可能多的字符来工作,以便为该模式的其余部分让路。
例如,对字符串hello world
的正则表达式.*world
将首先尝试吞下整个字符串并将其放入.*
。 但它不能,因为world
不能匹配,所以.*
开始放弃字符,直到它放弃了原始字符串中的world
- 在这种情况下,整个正则表达式可以匹配。
懒惰的量词 - 以相似的方式工作,除了相反。 他们希望匹配尽可能少的字符,并且他们做同样的事情,逐个添加更多的字符,直到模式的其余部分有匹配的机会
但根据我阅读的这篇文章,这些贪婪和懒惰量词的看似相同的过程是不同的 - 因为只有懒惰的量词才有必要“回溯”。 但是不要贪婪的量词在吐出先前被吞噬的元素时也需要“回溯”?
为什么会这样? 它看起来很直观
贪婪和懒惰的量词在正确应用时同样(昂贵)。 然而,懒惰的量词有一个不好的名声,因为它们可以并且经常用于补偿模式中的不精确性。
考虑一个简单的例子: <.*?>
与<.*>
。
当两个表达式都应用于相同的输入时
<abcdefghijklmnopqrstuvwxyz0123456789>
它们完全匹配相同的文本。 区别仅在于他们如何抵达比赛:“懒惰”表达式尝试越来越长的字符串,经过40步(演示1)后到达比赛。 另一方面,贪婪的表情一路走到最后,并且只经过5个步骤就回退一次(演示2)。
请注意,如果在>
后面添加更多字符,则情况可能会颠倒过来:
<abcdefghijklmnopqrstuvwxyz0123456789>abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789
现在贪婪的表情变成了“缓慢的表情”,采取了149个步骤(演示3),而懒惰的表情继续采用与之前相同的40个步骤(演示4)。
有时候贪心很糟糕。
示例[asdfsikbfqew0787072143k*(*&^(**&]
长凳
Regex1: [[^]]*]
Options: < none >
Completed iterations: 200 / 200 ( x 1000 )
Matches found per iteration: 1
Elapsed Time: 0.48 s, 476.21 ms, 476211 µs
Regex2: [.*?]
Options: < none >
Completed iterations: 200 / 200 ( x 1000 )
Matches found per iteration: 1
Elapsed Time: 0.32 s, 322.73 ms, 322730 µs
永远,但永远不要贪婪的点,除非它要求在行尾的残余。
有人曾经告诉我,这个(?=.*d)
是一个从下一个字符开始检查的前瞻。 这绝对是错误的。
这立即将指针设置为字符串的结尾,并开始检查
向后(回溯)。 小心这个,因为它跳过了一切。
它比观看油漆干燥要慢。
我总是使用贪婪,现在我只是在强迫时才使用它,而且
我不推荐给任何人。
上一篇: Why are greedy quantifiers less expensive than lazy quantifiers