非回溯子表达式如何工作“(?> exp)”

时间:2012-07-24 13:45:18

标签: c# .net regex

我正试图在正则表达式上变得更好。我很难理解(?> expression )的含义。我在哪里可以找到有关非倒缝亚咖啡的更多信息? THIS链接的说明如下:

  

贪婪子表达式,也称为非回溯子表达式。   这只匹配一次,然后不参加   回溯。

这个其他链接:http://msdn.microsoft.com/en-us/library/bs2twtah(v=vs.71).aspx也有非回溯子表达式的定义,但我仍然很难理解它的含义加上我想不出一个我将使用{{1 }}

3 个答案:

答案 0 :(得分:10)

与往常一样,regular-expressions.info是一个很好的起点。

如果您想确保曾经匹配的内容将保持匹配的一部分,请使用原子组。

例如,为了匹配可能或可能不用空格分隔的多个“单词”,然后是冒号,用户尝试使用正则表达式:

(?:[A-Za-z0-9_.&,-]+\s*)+:

当有比赛时,一切都很好。但是当没有时,由于灾难性的回溯,他的PC将因100%的CPU负载而无响应,因为正则表达式引擎会徒劳地试图找到匹配的单词组合,这将允许后面的冒号匹配。这当然是不可能的。

通过使用原子组,可以防止这种情况:

(?>[A-Za-z0-9_.&,-]+\s*)+:

现在匹配的任何东西都保持匹配 - 没有回溯,因此快速失败。

我最近遇到的另一个好例子是:

如果要匹配所有未跟随ASCII字母的数字,您可能需要使用正则表达式\d+(?![A-Za-z])。但是,这会因123a之类的输入而失败,因为正则表达式引擎会通过回溯来快速返回匹配12,直到后面的字符不再是字母为止。如果您使用(?>\d+)(?![A-Za-z]),则不会发生这种情况。 (当然,\d+(?![\dA-Za-z])也可以)

答案 1 :(得分:8)

正则表达式教程在此处有一个页面:http://www.regular-expressions.info/atomic.html

它的作用基本上是丢弃回溯信息,这意味着a(?>bc|b)c匹配abcc但不匹配abc

它与第二个字符串不匹配的原因是因为它找到了与bc匹配的内容,并丢弃了有关bc|b替换的回溯信息。它基本上忘记了它的|b部分。因此,c之后没有bc,匹配失败。

使用原子组的最有用方法是调用慢速正则表达式。您可以在上述页面上找到更多信息。

答案 2 :(得分:1)

阅读possessive quantifiers [a-z]*+,使回溯引擎只记住与之前匹配的所有步骤不匹配的上一步。

当很多可接受的步骤很可能时,这很有用,如果为了任何可能的回溯回归存储每个步骤,它们会占用内存。

占有量词是原子团的简写。