有人可以解释为什么以下代码......
#!/opt/local/bin/perl
use strict;
use warnings;
my $string;
$string = "\t\t\tEntry";
print "String: >$string<\n";
$string =~ s/^(\t*)//gi;
print "\$1: >$1<\n";
print "String: >$string<\n";
print "\n";
$string = "\t\t\tEntry";
$string =~ s/^(\t*)([^\t]+)/$2/gi;
print "\$1: >$1<\n";
print "String: >$string<\n";
print "\n";
exit 0;
...产生以下输出......
String: > Entry<
Use of uninitialized value in concatenation (.) or string at ~/sandbox.pl line 12.
$1: ><
String: >Entry<
$1: > <
String: >Entry<
...或更直接:为什么第一次替换中的匹配值不会保留在$ 1中?
答案 0 :(得分:7)
我在Perl 5.12的两个实现上尝试了这个,并没有遇到问题。 5.8做了。
因为你有g
选项,perl会尝试匹配模式,直到它失败。请参阅下面的调试输出。
所以它在Perl 5.8中不起作用,但这个确实:
my $c1;
$string =~ s/^(\t*)/$c1=$1;''/ge;
因此,每次匹配时,都会将其保存到$c1
。
这是use re 'debug'
告诉我的事情:
Compiling REx `^(\t*)'
size 9 Got 76 bytes for offset annotations.
first at 2
1: BOL(2)
2: OPEN1(4)
4: STAR(7)
5: EXACT <\t>(0)
7: CLOSE1(9)
9: END(0)
anchored(BOL) minlen 0
Offsets: [9]
1[1] 2[1] 0[0] 5[1] 3[1] 0[0] 6[1] 0[0] 7[0]
Compiling REx `^(\t*)([^\t]+)'
size 25 Got 204 bytes for offset annotations.
first at 2
1: BOL(2)
2: OPEN1(4)
4: STAR(7)
5: EXACTF <\t>(0)
7: CLOSE1(9)
9: OPEN2(11)
11: PLUS(23)
12: ANYOF[\0-\10\12-\377{unicode_all}](0)
23: CLOSE2(25)
25: END(0)
anchored(BOL) minlen 1
Offsets: [25]
1[1] 2[1] 0[0] 5[1] 3[1] 0[0] 6[1] 0[0] 7[1] 0[0] 13[1] 8[5] 0[0] 0[0] 0[0] 0[0] 0[0] 0[0] 0[0] 0[0] 0[0] 0[0] 14[1] 0[0] 15[0]
String: > Entry<
Matching REx `^(\t*)' against ` Entry'
Setting an EVAL scope, savestack=5
0 <> < Entry> | 1: BOL
0 <> < Entry> | 2: OPEN1
0 <> < Entry> | 4: STAR
EXACT <\t> can match 3 times out of 2147483647...
Setting an EVAL scope, savestack=5
3 < > <Entry> | 7: CLOSE1
3 < > <Entry> | 9: END
Match successful!
match pos=0
Use of uninitialized value in substitution iterator at - line 11.
Matching REx `^(\t*)' against `Entry'
Setting an EVAL scope, savestack=5
3 < > <Entry> | 1: BOL
failed...
Match failed
Freeing REx: `"^(\\t*)"'
Freeing REx: `"^(\\t*)([^\\t]+)"'
因为您尝试在行的开头匹配空格,所以既不需要g
也不需要i
。所以你可能会尝试做别的事情。
答案 1 :(得分:2)
我认为版本5.10及更高版本,只有在匹配时才会影响捕获缓冲区
在你的例子中,有趣的是$string =~ s/^(\t*)([^\t]+)/$2/gi;
它没有重置捕获缓冲区。这似乎是因为有一个序言预测
如果匹配应该尝试。在这种情况下,([^\t]+)
消耗了第一个中的整个字符串
匹配,所以发生string too short
并且缓冲区从未重置。
我无法测试,但$string =~ s/^(\t*)([^\t])//gi
应该发出同样的警告
if ( s///g ) {}
并且在这种情况下对捕获缓冲区的测试不一定包含
任何东西。 5.8版就是这种情况。即使在以后的版本中,它也只是一个调试功能。
编辑 @theracoon - 关于你的评论:“我有理由确定([^ \ t] +)实际上没有消耗整个字符串。输出绝对不反映那个。“
这证明你的正则表达式在第一场比赛中消耗了整个字符串,传递1 第二遍没有什么可以匹配的。这就是/ g修饰符的工作方式 它尝试再次匹配整个正则表达式,在最后一个匹配停止的字符串中的位置。
use re 'debug';
$string = "\t\t\tEntry";
$string =~ s/^(\t*)([^\t]+)/$2/gi;
print "'$string'\n";
通过1 ..
将REx "^(\t*)([^\t]+)"
与"%t%t%tEntry"
匹配
8&lt; %t%t%tEntry
&gt; &LT;&GT;
匹配成功!
通过2 ..
将REx "^(\t*)([^\t]+)"
与""
匹配
(没有,没有什么可以匹配的)
字符串太短[regexec_flags] ...
比赛失败了
'进入'