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