* +量词究竟做了什么?

时间:2013-08-05 20:48:41

标签: regex quantifiers

懒惰和贪婪的想法很容易理解,但我只在我的正则表达式中使用*+一次(在Java中)[A]|[^B]*+(?!C)(A,B,C是任意值)因为它在惰性修饰符导致StackOverflow错误时起作用。

由于大多数搜索引擎无法搜索符号,我找不到任何关于此的文档。那么* +究竟做了什么以及如何做到这一点?

3 个答案:

答案 0 :(得分:7)

贪婪的量词匹配它所能做的一切,然后模式回溯直到匹配成功。

延迟量词前向跟踪直到匹配成功。

占有量词可以匹配所有内容,并且永远不会回溯

+表示占有量词。例如,可以用作++*+

这种阻止回溯的能力意味着它可以停止catastrophic backtracking

答案 1 :(得分:2)

正如其他答案所指出的,*+是一个“占有量词”它尽可能多地匹配前一个元素,就像一个贪婪的量词,但从不回溯。

为什么这有用吗? 作为效果优化。此外,作为正则表达式不匹配时的性能优化 。这是理解正则表达式的重要一点:当它们匹配时,它们的最坏情况性能总是会发生。

根据正在使用的正则表达式引擎以及正则表达式本身的详细信息,最坏情况下的性能有时会非常糟糕。举一个简单的示例,请使用此正则表达式:a*a*a*b,与此字符串匹配:aaaaac

面对这种情况,标准的“NFA”型正则表达式引擎将执行以下操作:

  1. 尝试匹配第一个a 5次,第二个a零次,第三个a零次。
  2. 尝试将bc匹配 - 它失败。
  3. “Backtrack”并匹配第一a次,第二次1次,第三次零次。
  4. 再次尝试匹配b - 它失败。
  5. 再次回溯,尝试第1次a 4次,第2次零次,第3次1次。
  6. ...
  7. Backtrack,尝试第1 a次,第2次,第2次,第3次零次......
  8. (我想你可以自己填写接下来的几百个步骤。)

    如果正则表达式是a*+a*a*b,那将永远不会发生。这更像是:

    1. 尝试匹配第1 a次,第2次零次,第3次零次。
    2. 尝试匹配b - 它失败。
    3. 由于第一个a是“占有”,一旦匹配5次,它就永远不会尝试匹配较少的次数。并且由于字符串中没有剩余a s以供其他a*匹配,因此它们只能匹配零次。没有什么可以尝试的,所以整场比赛都失败了。
    4. 没有第4步。你已经完成了。当你的朋友们正在等待他们的regexp完成执行时,你可以放松脚跟并打开你选择的冷饮。

答案 2 :(得分:1)

X * +表示X,零次或多次(占有)

占有量词总是占用整个输入字符串,尝试一次(并且只有一次)匹配。与贪婪的量词不同,占有量词永远不会退缩,即使这样做也会使整体匹配成功。