为什么';t.*是否使用此Perl正则表达式中的整个字符串?
为什么第一个print语句没有输出我期望的结果:为什么';t.*是否使用此Perl正则表达式中的整个字符串?,perl,regex,Perl,Regex,为什么第一个print语句没有输出我期望的结果: first = This is a test string, sec = This is a test string 既然*和+都是贪婪的,为什么在第一个匹配中,*的内部,即“(”)的内部不消耗整个字符串 use strict; use warnings; my $string = "This is a test string"; $string =~ /((.*)*)/; print "first = $1, sec = $2\n";
first = This is a test string, sec = This is a test string
既然*和+都是贪婪的,为什么在第一个匹配中,*的内部,即“(”)的内部不消耗整个字符串
use strict;
use warnings;
my $string = "This is a test string";
$string =~ /((.*)*)/;
print "first = $1, sec = $2\n"; #prints "first = This is a test string, sec ="
$string =~ /((.+)*)/;
print "first = $1, sec = $2\n"; #prints "first = This is a test string, sec = This is a test string"
在第一个正则表达式中,
*
匹配两次。第一次匹配整个字符串。第二次匹配末尾的空字符串,因为当没有其他匹配项时,*
匹配空字符串
另一个正则表达式不会出现这种情况,因为+
无法匹配空字符串
编辑:至于哪里去了:$2将包含上次应用*
/+
时匹配的内容。$1将包含(.*)*
/(.+)*
匹配的内容,即整个字符串。使用“”运行它将导致:
Compiling REx "((.*)*)"
Final program:
1: OPEN1 (3)
3: CURLYX[0] {0,32767} (12)
5: OPEN2 (7)
7: STAR (9) # <====
8: REG_ANY (0)
9: CLOSE2 (11)
11: WHILEM[1/1] (0)
12: NOTHING (13)
13: CLOSE1 (15)
15: END (0)
minlen 0
编译REx”((.*)”
最终课程:
1:OPEN1(3)
3:CURLYX[0]{032767}(12)
5:OPEN2(7)
7:STAR(9)| 11:WHILEM[1/1](0)
whilem:匹配0中的1..32767
21<测试字符串>| 5:OPEN2(7)
21| 7:STAR(9)| 9:CLOSE2(11)| 11:WHILEM[1/1](0)
whilem:匹配0中的2..32767
whilem:检测到空匹配,正在尝试继续。。。
# --------------------------------------------------------------------------------------------
21<测试字符串>| 12:无(13)
21<测试串>| 13:CLOSE1(15)
21<测试串>| 15:结束(0)
比赛成功!
编译REx”((.+)*)
最终课程:
1:OPEN1(3)
3:CURLYX[0]{032767}(12)
5:OPEN2(7)
7:PLUS(9)| 11:WHILEM[1/1](0)
whilem:匹配0中的1..32767
21<测试字符串>| 5:OPEN2(7)
21<测试字符串>| 7:PLUS(9)| 13:CLOSE1(15)
21<测试串>| 15:结束(0)
比赛成功!
第一个正则表达式的问题是,()*
只保存最后一个匹配项,而*
匹配一个空字符串(即无)。因此
"aaab" =~ /(.)*/;
$1
将是“b”
。如果将该行为与*
匹配空字符串的事实结合起来,则可以看到内部捕获有两个匹配项:“这是一个测试字符串”和“”。由于空字符串是最后一个出现的,因此它被保存到$2
$1
是整个捕获,因此它相当于“这是一个测试字符串”。”
。第二种情况的效果与您预期的一样,因为+
将不匹配空字符串。我没有答案,但我有不同的方法来构建问题,使用更简单、可能更现实的正则表达式
前两个示例的行为与我预期的完全相同:*
使用整个字符串,正则表达式返回只有一个元素的列表。但第三个正则表达式返回有两个元素的列表
use strict;
use warnings;
use Data::Dumper;
$_ = "foo";
print Dumper( [ /^(.*)/g ] ); # ('foo') As expected.
print Dumper( [ /.(.*)/g ] ); # ('oo') As expected.
print Dumper( [ /(.*)/g ] ); # ('foo', '') Why?
到目前为止,许多答案都强调,*
将匹配任何内容。虽然这是真的,但这一回答并没有触及问题的核心,即:为什么正则表达式引擎仍在搜索*
已消耗完整个字符串?在其他情况下(如前两个示例),*
不会为了更好的度量而抛出额外的空字符串
在Chas.Owens的有用注释后更新。对三个示例中的任何一个的第一次评估都会导致
*
匹配整个字符串。如果我们当时可以干预并调用pos()
,引擎将确实位于字符串的末尾(至少当我们看到字符串时;请参阅Chas.的评论,以了解更多关于此的信息)但是,/g
选项告诉Perl再次尝试匹配整个正则表达式。第二次尝试对于示例1和2将失败,失败将导致引擎停止搜索。但是,对于正则表达式3,引擎将获得另一个匹配:空字符串。然后,/g
选项告诉引擎尝试整个模式再一次。现在真的没有什么可匹配的了——既没有常规字符,也没有尾随的空字符串——因此过程停止。对。但是由于括号包围了字符串,我希望括号内的全部内容都是$2(而不仅仅是*),那么外部()匹配结束?根据你的描述,我会猜到$3,但它没有出现。@Anna组是由左括号计算的,所以$1是整个字符串,其中$2是括号的内部集合。内部匹配实际上是$2
,外部匹配是$1
。当内部部分第二次匹配时,它“覆盖”从第一次匹配时捕获的输出。如果内部(.*)
匹配多次,则只有最后一次匹配被保留为$2
@sepp2k,因为正则表达式匹配从内部*开始,它必须消耗整个字符串。那么,为什么在第一种情况下$2为空?更好的问题是“为什么这样做?”:)这仅仅是因为你对这个奇怪的边缘案例感到好奇,还是你真的在尝试使用它?Brian,我只是好奇:-)请参阅“perldoc-re”或perldoc.perl.org/re.html,这会让你想到“perldoc-perldebug”还有。@Brad&Ether:是的,老实说,我希望自己能冷静一些,理解那种输出,但我几乎无法理解。Ether指向的链接是这样的,对此我只能说,阿门:“为了理解这一典型的大量输出,人们不仅必须了解正则表达式匹配的一般工作原理,还必须了解Perl的
Matching REx "((.+)*)" against "This is a test string"
0 <> <This is a > | 1:OPEN1(3)
0 <> <This is a > | 3:CURLYX[0] {0,32767}(12)
0 <> <This is a > | 11: WHILEM[1/1](0)
whilem: matched 0 out of 0..32767
0 <> <This is a > | 5: OPEN2(7)
0 <> <This is a > | 7: PLUS(9) # <====
REG_ANY can match 21 times out of 2147483647...
21 < test string> <> | 9: CLOSE2(11)
21 < test string> <> | 11: WHILEM[1/1](0)
whilem: matched 1 out of 0..32767
21 < test string> <> | 5: OPEN2(7)
21 < test string> <> | 7: PLUS(9) # <====
# This is where the outputs really start to diverge
# ------------------------------------------------------------------------------------
REG_ANY can match 0 times out of 2147483647...
failed... # <==== Failed
whilem: failed, trying continuation...
# ------------------------------------------------------------------------------------
21 < test string> <> | 12: NOTHING(13)
21 < test string> <> | 13: CLOSE1(15)
21 < test string> <> | 15: END(0)
Match successful!
"aaab" =~ /(.)*/;
use strict;
use warnings;
use Data::Dumper;
$_ = "foo";
print Dumper( [ /^(.*)/g ] ); # ('foo') As expected.
print Dumper( [ /.(.*)/g ] ); # ('oo') As expected.
print Dumper( [ /(.*)/g ] ); # ('foo', '') Why?