7

我有以下文字

tooooooooooooon

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

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

它应该返回ton不应该吗?

知道为什么吗?

4

5 回答 5

46

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

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

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

toooooooonoooooon

此正则表达式(未指定 'o')

t.*n

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

toooooooonoooooon

但是正则表达式

t.*?n

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

toooooooon
于 2008-10-29T09:36:09.553 回答
5

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

你的表情是这样说的:

一个“t”,后跟*尽可能少的*“o”,然后是一个“n”。

这意味着任何必要的 o 都将被匹配,因为末尾有一个 'n',表达式渴望达到。匹配所有的 o 是成功的唯一可能性。

于 2008-10-29T09:44:46.040 回答
4

正则表达式尝试匹配其中的所有内容。因为要匹配的 'o' 不比匹配 n 的每个 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
于 2008-10-29T09:37:10.563 回答
4

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

最小 RE 成功:

'toooooon' ~~ /to*?n/

 太棒了       
{t} 匹配 [t]
[t] 匹配 [o] 0 次
[t]<n> 匹配失败 [n] -> 重试 [o]
[t]{o} 匹配 [o] 1 次
[t][o]<n> 匹配失败 [n] -> 重试 [o]
[t][o]{o} 匹配 [o] 2 次
[t][o][o]<n> 匹配失败 [n] -> 重试 [o]

. . . .

[t][o][o][o][o]{o} 匹配 [o] 5 次
[t][o][o][o][o][o]<n> 匹配失败 [n] -> 重试 [o]
[t][o][o][o][o][o]{o} 匹配 [o] 6 次
[t][o][o][o][o][o][o]{n} 匹配 [n]

正常 RE 成功:

(注意:Maximal RE 类似)

'太棒了' ~~ /to*n/

 太棒了       
{t} 匹配 [t]
[t]{o}{o}{o}{o}{o}{o} 匹配 [o] 6 次
[t][o][o][o][o][o][o]{n} 匹配 [n]

最小 RE 失败:

'toooooo' ~~ /to*?n/

 太棒了

. . . .

. . . .

[t][o][o][o][o]{o} 匹配 [o] 5 次
[t][o][o][o][o][o]<n> 匹配失败 [n] -> 重试 [o]
[t][o][o][o][o][o]{o} 匹配 [o] 6 次
[t][o][o][o][o][o][o]<n> 匹配失败 [n] -> 重试 [o]
[t][o][o][o][o][o][o]<o> 匹配失败 [o] 7 次 -> 匹配失败

正常 RE 失败:

'toooooo' ~~ /to*n/

 太棒了       
{t} 匹配 [t]
[t]{o}{o}{o}{o}{o}{o} 匹配 [o] 6 次
[t][o][o][o][o][o][o]<n> 匹配失败 [n] -> 重试 [o]
[t][o][o][o][o][o] 匹配 [o] 5 次
[t][o][o][o][o][o]<n> 匹配失败 [n] -> 重试 [o]

. . . .

[t][o] 匹配 [o] 1 次
[t][o]<o> 匹配失败 [n] -> 重试 [o]
[t] 匹配 [o] 0 次
[t]<n> 匹配失败 [n] -> 匹配失败

最大 RE 失败:

'toooooo' ~~ /to*+n/

 太棒了
{t} 匹配 [t]
[t]{o}{o}{o}{o}{o}{o} 匹配 [o] 6 次
[t][o][o][o][o][o][o]<n> 匹配失败 [n] -> 匹配失败
于 2008-10-30T02:01:39.127 回答
2

您正在搜索的字符串(就像是大海捞针)不包含子字符串“ton”。

然而,它确实包含子字符串“tooooooooooooon”。

于 2008-10-29T09:35:08.180 回答