Regex 正则表达式nongreedy是贪婪的
我有以下文字Regex 正则表达式nongreedy是贪婪的,regex,regex-greedy,non-greedy,Regex,Regex Greedy,Non Greedy,我有以下文字 tooooooooooooon 根据我正在读的这本书,当?跟在任何量词后面时,它就变得不贪婪了 我的正则表达式to*?n仍在返回tooooooon 它应该返回ton不是吗 知道原因吗?您正在搜索的字符串(原为干草堆)不包含子字符串“ton” 但是,它确实包含子字符串“tooooon”。正则表达式只能匹配实际存在的文本片段 因为子字符串“ton”在字符串中的任何位置都不存在,所以它不能是匹配的结果。匹配将只返回原始字符串的子字符串 编辑:为了清楚起见,如果您使用下面的字符串,请使用
tooooooooooooon
根据我正在读的这本书,当?
跟在任何量词后面时,它就变得不贪婪了
我的正则表达式to*?n
仍在返回tooooooon
它应该返回ton
不是吗
知道原因吗?您正在搜索的字符串(原为干草堆)不包含子字符串“ton”
但是,它确实包含子字符串“tooooon”。正则表达式只能匹配实际存在的文本片段 因为子字符串“ton”在字符串中的任何位置都不存在,所以它不能是匹配的结果。匹配将只返回原始字符串的子字符串 编辑:为了清楚起见,如果您使用下面的字符串,请使用额外的“n”
toooooooonoooooon
此正则表达式(不指定“o”)
将匹配以下内容(在“n”之前尽可能多的字符)
但是正则表达式
t.*?n
将仅匹配以下内容(在“n”之前尽可能少的字符)
regexp尝试匹配其中的所有内容。因为要匹配的“o”不少于Tooon中匹配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
正则表达式总是渴望匹配 你的表情是这样的: A 't', followed by *as few as possible* 'o's, followed by a 'n'. 一个“t”,后面跟着*尽可能少的*“o”,后面跟着一个“n”。
这意味着任何必要的o都将被匹配,因为在末尾有一个“n”,这是表达式渴望达到的。匹配所有o是成功的唯一可能性。正则表达式总是尽最大努力匹配。在这种情况下,您要做的唯一一件事就是让解析器回溯到
/o*?/
节点,从而减慢解析器的速度。在“tooooon”
中,每个'o'
一次。而对于正常匹配,第一次通过时需要尽可能多的'o'
s。由于要匹配的下一个元素是'n'
,它不会被'o'
匹配,因此尝试使用最小匹配没有什么意义。事实上,当正常匹配失败时,需要相当长的时间才能失败。它必须回溯每一个'o'
,直到没有任何东西可以回溯。在这种情况下,我实际上会使用最大匹配/到*+n/
。'o'
会尽其所能拿走所有东西,并且永远不会归还任何东西。这将使它在失败时迅速失败
最小重复次数:
“Tooooon”~~~/to*?n/
t o o o o n
{t} 匹配[t]
[t] 匹配[o]0次
[t] 无法匹配[n]->重试[o]
[t] {o}匹配[o]1次
[t] [o]无法匹配[n]->重试[o]
[t] [o]{o}匹配[o]2次
[t] [o][o]无法匹配[n]->重试[o]
. . . .
[t] [o][o][o][o]{o}匹配[o]5次
[t] [o][o][o][o][o]未能匹配[n]->重试[o]
[t] [o][o][o][o][o]{o}匹配[o]6次
[t] [o][o][o][o][o][o]{n}匹配[n]
正常再成功:
(注:最大RE类似)
“Tooooon”~~~/to*n/
t o o o o n
{t} 匹配[t]
[t] {o}{o}{o}{o}{o}{o}{o}匹配[o]6次
[t] [o][o][o][o][o][o]{n}匹配[n]
最小RE故障:
“Tooooo”~~~/to*?n/
托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托
. . . .
. . . .
[t] [o][o][o][o]{o}匹配[o]5次
[t] [o][o][o][o][o]未能匹配[n]->重试[o]
[t] [o][o][o][o][o]{o}匹配[o]6次
[t] [o][o][o][o][o]未能匹配[n]->重试[o]
[t] [o][o][o][o][o]匹配失败[o]7次->匹配失败
正常RE的故障:
“tooooo”~~~/to*n/
托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托
{t} 匹配[t]
[t] {o}{o}{o}{o}{o}{o}{o}匹配[o]6次
[t] [o][o][o][o][o]未能匹配[n]->重试[o]
[t] [o][o][o][o][o]匹配[o]5次
[t] [o][o][o][o][o]未能匹配[n]->重试[o]
. . . .
[t] [o]匹配[o]1次
[t] [o]无法匹配[n]->重试[o]
[t] 匹配[o]0次
[t] 未能匹配[n]->匹配失败
最大RE失效:
“Tooooo”~~~/to*+n/
托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托
{t} 匹配[t]
[t] {o}{o}{o}{o}{o}{o}{o}匹配[o]6次
[t] [o][o][o][o][o]未能匹配[n]->匹配失败
进一步说,正则表达式只能返回它能找到的内容。它无法在您的字符串中找到“ton”,因为它不存在,但它可以找到“tooooon”。很好的注释,为了清晰起见,我将添加它。您也可以使用regx替换,但它只替换匹配项。非常清楚的解释!我认为您的最后一个示例应该从“t.*n”更改为“to*?n”--实际上,“t.*n”匹配整个字符串。亚当:不,你自己用你最喜欢的语言试试——我用过——你的答案应该是一样的。全部*?确实是找到最短的匹配,而不是最长的。我会使用相同的字符串来测试。让你更清楚你想要强调什么。
toooooooon
$a = "toooooo";
$b = "toooooon";
if ($a =~ m/(to*?)/) {
print $1,"\n";
}
if ($b =~ m/(to*?n)/) {
print $1,"\n";
}
~>perl ex.pl
t
toooooon
A 't', followed by *as few as possible* 'o's, followed by a 'n'.
'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]
'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]
'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
'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
'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