懒惰和贪婪的想法很容易理解,但我只在我的正则表达式中使用*+
一次(在Java中)[A]|[^B]*+(?!C)
(A,B,C是任意值)因为它在惰性修饰符导致StackOverflow错误时起作用。
由于大多数搜索引擎无法搜索符号,我找不到任何关于此的文档。那么* +究竟做了什么以及如何做到这一点?
答案 0 :(得分:7)
贪婪的量词匹配它所能做的一切,然后模式回溯直到匹配成功。
延迟量词前向跟踪直到匹配成功。
占有量词可以匹配所有内容,并且永远不会回溯。
+
表示占有量词。例如,可以用作++
或*+
。
这种阻止回溯的能力意味着它可以停止catastrophic backtracking。
答案 1 :(得分:2)
正如其他答案所指出的,*+
是一个“占有量词”它尽可能多地匹配前一个元素,就像一个贪婪的量词,但从不回溯。
为什么这有用吗? 仅作为效果优化。此外,仅作为正则表达式不匹配时的性能优化 。这是理解正则表达式的重要一点:当它们不匹配时,它们的最坏情况性能总是会发生。
根据正在使用的正则表达式引擎以及正则表达式本身的详细信息,最坏情况下的性能有时会非常糟糕。举一个简单的示例,请使用此正则表达式:a*a*a*b
,与此字符串匹配:aaaaac
。
面对这种情况,标准的“NFA”型正则表达式引擎将执行以下操作:
a
5次,第二个a
零次,第三个a
零次。b
与c
匹配 - 它失败。a
次,第二次1次,第三次零次。b
- 它失败。a
4次,第2次零次,第3次1次。a
次,第2次,第2次,第3次零次...... (我想你可以自己填写接下来的几百个步骤。)
如果正则表达式是a*+a*a*b
,那将永远不会发生。这更像是:
a
次,第2次零次,第3次零次。b
- 它失败。a
是“占有”,一旦匹配5次,它就永远不会尝试匹配较少的次数。并且由于字符串中没有剩余a
s以供其他a*
匹配,因此它们只能匹配零次。没有什么可以尝试的,所以整场比赛都失败了。答案 2 :(得分:1)
X * +表示X,零次或多次(占有)
占有量词总是占用整个输入字符串,尝试一次(并且只有一次)匹配。与贪婪的量词不同,占有量词永远不会退缩,即使这样做也会使整体匹配成功。