初学者的问题。在代码中:
$a = 'aaagggaaa';
(@b) = ($a =~ /(a.+)(g.+)/);
print "$b[0]\n";
为什么$b[0]
等于 aaagg
而不是 aaa
?换句话说 - 为什么第二组 - (g.+)
- 仅匹配最后一个g
?
答案 0 :(得分:3)
因为第一个.+
是"贪婪",这意味着它会尝试匹配尽可能多的字符。
如果你想证明这个"贪心"行为,您可以将.+
替换为.+?
,以便/(a.+?)(g.+)/
返回(' aaa',' gggaaa')。
也许,您想写/(a+)(g+)/
(只有第一组中的'以及第二组中的')。
答案 1 :(得分:1)
Perl正则表达式通常匹配可能的最长字符串。
在您的代码中,它与上一个g
匹配,并返回输出 aaagg 。如果要将输出作为 aaa ,则需要使用非贪婪行为。使用此代码:
$a = 'aaagggaaa';
(@b) = ($a =~ /(a.+?)(g.+)/);
print "$b[0]\n";
将输出:
aaa
显然,使用question mark
会使匹配不合理。
答案 2 :(得分:1)
你写的正则表达式:
($a =~ /(a.+)(g.+)/);
尽可能抓住"a"
和任何字词,在一个"g"
中完成后跟更多字符。因此,第一个(a.+)
只匹配"aaagg"
,直到正则表达式的第二部分匹配为止:(g.+)
=> "gaaa"
@b
数组会收到两个匹配"aaagg"
和"gaaa"
。因此,$b[0]
只打印"aaagg"
。
答案 3 :(得分:1)
问题在于,第一个.+
导致g
尽可能向右匹配。
为了向您展示实际发生的情况,我修改了您的代码以输出更多说明性的debug信息。
$ perl -Mre=debug -e'q[aaagggaaa] =~ /a.+[g ]/'
Compiling REx "a.+[g ]"
Final program:
1: EXACT <a> (3)
3: PLUS (5)
4: REG_ANY (0)
5: ANYOF[ g][] (16)
16: END (0)
anchored "a" at 0 (checking anchored) minlen 3
Guessing start of match in sv for REx "a.+[g ]" against "aaagggaaa"
Found anchored substr "a" at offset 0...
Guessed: match at offset 0
Matching REx "a.+[g ]" against "aaagggaaa"
0 <> <aaagggaaa> | 1:EXACT <a>(3)
1 <a> <aagggaaa> | 3:PLUS(5)
REG_ANY can match 8 times out of 2147483647...
9 <aaagggaaa> <> | 5: ANYOF[ g][](16)
failed...
8 <aaagggaa> <a> | 5: ANYOF[ g][](16)
failed...
7 <aaaggga> <aa> | 5: ANYOF[ g][](16)
failed...
6 <aaaggg> <aaa> | 5: ANYOF[ g][](16)
failed...
5 <aaagg> <gaaa> | 5: ANYOF[ g][](16)
6 <aaaggg> <aaa> | 16: END(0)
Match successful!
Freeing REx: "a.+[g ]"
请注意,第一个.+
正在捕捉它可以开始的所有内容
然后它必须回溯直到g
可以匹配。
你可能想要的是:
/( a+ )( g+ )/x;
/( a.+? )( g.+ )/x;
/( a+ )( g.+ )/x;
/( a[^g]+ )( g.+ )/x;
/( a[^g]+ )( g+ )/x;
# etc.
如果没有您的更多信息,就无法知道您想要的正则表达式。
真正的正则表达式本身就是一种语言,比Perl的其余部分更复杂。
答案 4 :(得分:0)
通常正则表达式是贪婪的。您可以使用?
字符将其关闭:
$a = 'aaagggaaa';
my @b = ($a =~ /(a.+)(g.+)/);
my @c = ($a =~ /(a.+?)(g.+)/);
print "@b\n";
print "@c\n";
输出:
aaagg gaaa
aaa gggaaa
但我不确定这是你想要的!那么abagggbb
呢?您需要aba
?