我不得不承认,这个让我感到厌恶.
考虑以下代码:
use version;
use Data::Dumper;
my $codeLevel = q{6.1.0.7 (build 25.3.1103030000)};
print STDERR qq{$codeLevel\n};
my $vrmf;
if($codeLevel =~ /^\s*([0-9.]*) \(build.*\)/) {
print STDERR "$1\n";
$vrmf = version->parse($1);
}
print STDERR Dumper($vrmf);
Run Code Online (Sandbox Code Playgroud)
正如预期的那样,输出是:
6.1.0.7 (build 25.3.1103030000)
6.1.0.7
$VAR1 = bless( {
'original' => '6.1.0.7',
'qv' => 1,
'version' => [
6,
1,
0,
7
]
}, 'version' );
Run Code Online (Sandbox Code Playgroud)
但是,删除第二个打印:
use version;
use Data::Dumper;
my $codeLevel = q{6.1.0.7 (build 25.3.1103030000)};
print STDERR qq{$codeLevel\n};
my $vrmf;
if($codeLevel =~ /^\s*([0-9.]*) \(build.*\)/) {
$vrmf = version->parse($1);
}
print STDERR Dumper($vrmf);
Run Code Online (Sandbox Code Playgroud)
输出变为:
6.1.0.7 (build 25.3.1103030000)
$VAR1 = bless( {
'original' => '0',
'version' => [
0
]
}, 'version' );
Run Code Online (Sandbox Code Playgroud)
我找不到任何print
可能影响传递给它的变量的文档,或者它会影响正则表达式匹配变量.
有人可以向我解释这里发生了什么吗?
Perl中的标量值可以是数字和字符串同时.SV对象(SV =标量值)具有整数,浮点和字符串值的槽,以及标识哪些值在任何时间点有效的标记.当您使用值作为字符串时,perl会计算字符串值并设置一个标识为有效的标志.(其他操作,如添加1会使字符串值无效.)当您打印某些内容时(不出所料)将其用作字符串.你可以使用Devel :: Peek看到这个.
use Devel::Peek;
my $s = '6.1.0.7 (build 25.3.1103030000)';
if ($s =~ /^\s*([0-9.]*) \(build.*\)/) {
Dump($1);
printf STDERR "\$1 = $1\n";
Dump($1);
}
Run Code Online (Sandbox Code Playgroud)
结果是
SV = PVMG(0x1434ca4) at 0x144d83c
REFCNT = 1
FLAGS = (GMG,SMG)
IV = 0
NV = 0
PV = 0
MAGIC = 0x146c324
MG_VIRTUAL = &PL_vtbl_sv
MG_TYPE = PERL_MAGIC_sv(\0)
MG_OBJ = 0x144d82c
MG_LEN = 1
MG_PTR = 0x14631c4 "1"
$1 = 6.1.0.7
SV = PVMG(0x1434ca4) at 0x144d83c
REFCNT = 1
FLAGS = (GMG,SMG,pPOK)
IV = 0
NV = 0
PV = 0x1487a1c "6.1.0.7"\0
CUR = 7
LEN = 8
MAGIC = 0x146c324
MG_VIRTUAL = &PL_vtbl_sv
MG_TYPE = PERL_MAGIC_sv(\0)
MG_OBJ = 0x144d82c
MG_LEN = 1
MG_PTR = 0x14631c4 "1"
Run Code Online (Sandbox Code Playgroud)
请注意,在第二个转储输出中,已填充PV槽(字符串值),并且已在FLAGS下添加了pPOK标志.
所以,是的,print
有一种副作用,虽然在正常情况下你不应该注意到.version->parse()
似乎期望一个字符串参数,但不会触发字符串语义.鉴于version
喜欢使用XS实现,它可能是一个bug而不是perl.请注意,制作捕获数据的副本会导致问题消失:
use Data::Dump qw'pp';
my $s = '6.1.0.7 (build 25.3.1103030000)';
if ($s =~ /^\s*([0-9.]*) \(build.*\)/) {
my $x = $1;
pp(version->parse($x));
}
Run Code Online (Sandbox Code Playgroud)
结果:
bless({ original => "6.1.0.7", qv => 1, version => [6, 1, 0, 7] }, "version")
Run Code Online (Sandbox Code Playgroud)