正则表达非常贪婪

时间:2008-10-29 09:32:54

标签: regex regex-greedy

我有以下文字

tooooooooooooon

根据我正在阅读的这本书,当?跟随任何量词之后,它变得非贪婪。

我的正则表达式to*?n仍在返回tooooooooooooon

它应该返回ton不应该吗?

知道为什么吗?

5 个答案:

答案 0 :(得分:46)

正则表达式只能匹配实际存在的文本片段。

因为子字符串'ton'不存在于字符串中的任何位置,所以它不能是匹配的结果。匹配只返回原始字符串的子字符串

编辑:要清楚,如果您使用下面的字符串,请使用额外的'n'

toooooooonoooooon

这个正则表达式(没有指定'o')

t.*n

将匹配以下内容(在'n'之前尽可能多的字符)

toooooooonoooooon

但是正则表达式

t.*?n

只会匹配以下内容(在'n'之前尽可能少的字符)

toooooooon

答案 1 :(得分:5)

正则表达式总是渴望匹配。

你的表达是这样说的:

A 't', followed by *as few as possible* 'o's, followed by a 'n'.

这意味着任何必要的匹配都会匹配,因为结尾有一个'n',表达式很想达到。匹配所有o是唯一成功的可能性。

答案 2 :(得分:4)

Regexps尝试匹配其中的所有内容。因为与太阳中的每个o匹配并没有比匹配n更少的'o',所以一切都匹配。另外,因为你正在使用o *?而不是o +?你不需要o出席。

示例,在Perl中

$a = "toooooo";
$b = "toooooon";

if ($a =~ m/(to*?)/) {
        print $1,"\n";
}
if ($b =~ m/(to*?n)/) {
        print $1,"\n";
}

~>perl ex.pl
t
toooooon

答案 3 :(得分:4)

正则表达式总是尽力匹配。在这种情况下,您唯一要做的就是通过让解析器回溯到/o*?/节点来减慢解析器的速度。 'o'中的每个"tooooon"一次。然而,通过正常匹配,第一次通过时,可能需要尽可能多的'o' s。由于要匹配的下一个元素是'n''o'不匹配,因此尝试使用最小匹配几乎没有意义。实际上,当正常匹配失败时,它将需要很长时间才能失败。它必须回溯每个'o',直到没有任何东西可以回溯。在这种情况下,我实际上会使用最大匹配/to*+n/'o'将尽其所能,并且永远不会给予任何回报。这将使它在失败时迅速失败。

最小RE成功:

'toooooon' ~~ /to*?n/

 t  o  o  o  o  o  o  n       
{t}                           match [t]
[t]                           match [o] 0 times
[t]<n>                        fail to match [n] -> retry [o]
[t]{o}                        match [o] 1 times
[t][o]<n>                     fail to match [n] -> retry [o]
[t][o]{o}                     match [o] 2 times
[t][o][o]<n>                  fail to match [n] -> retry [o]

. . . .

[t][o][o][o][o]{o}            match [o] 5 times
[t][o][o][o][o][o]<n>         fail to match [n] -> retry [o]
[t][o][o][o][o][o]{o}         match [o] 6 times
[t][o][o][o][o][o][o]{n}      match [n]

正常RE成功:

(注意:类似于Maximal RE)

'toooooon' ~~ /to*n/

 t  o  o  o  o  o  o  n       
{t}                           match [t]
[t]{o}{o}{o}{o}{o}{o}         match [o] 6 times
[t][o][o][o][o][o][o]{n}      match [n]

最小RE的失败:

'toooooo' ~~ /to*?n/

 t  o  o  o  o  o  o

. . . .

. . . .

[t][o][o][o][o]{o}            match [o] 5 times
[t][o][o][o][o][o]<n>         fail to match [n] -> retry [o]
[t][o][o][o][o][o]{o}         match [o] 6 times
[t][o][o][o][o][o][o]<n>      fail to match [n] -> retry [o]
[t][o][o][o][o][o][o]<o>      fail to match [o] 7 times -> match failed

正常RE的失败:

'toooooo' ~~ /to*n/

 t  o  o  o  o  o  o       
{t}                           match [t]
[t]{o}{o}{o}{o}{o}{o}         match [o] 6 times
[t][o][o][o][o][o][o]<n>      fail to match [n] -> retry [o]
[t][o][o][o][o][o]            match [o] 5 times
[t][o][o][o][o][o]<n>         fail to match [n] -> retry [o]

. . . .

[t][o]                        match [o] 1 times
[t][o]<o>                     fail to match [n] -> retry [o]
[t]                           match [o] 0 times
[t]<n>                        fail to match [n] -> match failed

最大RE失败:

'toooooo' ~~ /to*+n/

 t  o  o  o  o  o  o
{t}                           match [t]
[t]{o}{o}{o}{o}{o}{o}         match [o] 6 times
[t][o][o][o][o][o][o]<n>      fail to match [n] -> match failed

答案 4 :(得分:2)

您正在搜索的字符串(干草堆原样)不包含子字符串“ton”。

但它包含子字符串“tooooooooooooon”。