Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Perl 为什么版本->;没有预先打印,解析无法工作?_Perl_Version - Fatal编程技术网

Perl 为什么版本->;没有预先打印,解析无法工作?

Perl 为什么版本->;没有预先打印,解析无法工作?,perl,version,Perl,Version,我得承认,这件事把我吓坏了 考虑以下代码: 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(

我得承认,这件事把我吓坏了

考虑以下代码:

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);
正如预期的那样,输出为:

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' );
但是,请删除第二个打印:

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);
输出变为:

6.1.0.7 (build 25.3.1103030000)
$VAR1 = bless( {
                 'original' => '0',
                 'version' => [
                                0
                              ]
               }, 'version' );
我找不到任何文档说明
print
会影响传递给它的变量,或者它会影响正则表达式匹配变量


有人能给我解释一下这里发生了什么事吗?

不总是这样吗;你问一个问题,然后找到答案

此代码:

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);
工作正常。请注意,此处已将$1字符串化


不过,这留下了一个有趣的观察结果:打印变量似乎会永久地将其字符串化

看起来像version::parse中的一个bug,它没有正确地触发传入参数的get magic


查看代码可以发现CPAN和核心“版本”中存在相同的问题;在处理“变魔术”之前很久就开始检查SvOK了。不幸的是,这将涉及模块代码和perl核心的修复。

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);
}
结果是

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"
请注意,在第二次转储输出中,PV插槽(字符串值)已填充,并且pPOK标志已添加到标志下

所以,是的,
print
有某种副作用,尽管在正常情况下你永远不会注意到
version->parse()
似乎需要一个字符串参数,但不会触发字符串语义。鉴于
version
更喜欢使用XS实现,这可能是一个bug,而不是perl中的bug。请注意,复制捕获数据会导致问题消失:

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));
}
结果:

bless({ original => "6.1.0.7", qv => 1, version => [6, 1, 0, 7] }, "version")

这是在MacOS X 10.6.8上使用Perl 5.14.1,使用“version”0.91(即version 0.91)的XS实现复制的

但是,它是
version::vxs
(XS实现)中的一个bug,而不是
version::vpp
(纯Perl)实现中的bug

use version::vxs;
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::vxs->parse($1);
}

print STDERR Dumper($vrmf);
正如你所展示的那样,这是失败的。当我编译纯Perl版本(
Perl Makefile.PL--Perl_only
,如自述文件中所述)并对其进行测试时,它工作正常:

$ perl -Iblib/lib x4.pl
6.1.0.7 (build 25.3.1103030000)
$VAR1 = bless( {
                 'original' => '6.1.0.7',
                 'qv' => 1,
                 'version' => [
                                6,
                                1,
                                0,
                                7
                              ]
               }, 'version::vpp' );

$ cat x4.pl
use version::vpp;
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::vpp->parse($1);
}

print STDERR Dumper($vrmf);
$

我认为你可以明智地(作者是JPEACOCK)。作为一种解决方法,手动安装纯Perl版本并删除XS版本(因为代码首先查找XS代码-请参阅)。如果你真的很勇敢,考虑一下实际的bug是什么。

< P>我不知道版本号背后的特殊魔法,但是用过载>代码>你几乎可以给出任何你想要严格化的副作用。
package My::Class;
use overload
    '""' => \&arbitrary_function;

...

$obj = My::Class->new();
print $obj;                 # invokes &arbitrary_function

是,
print
需要字符串版本才能打印。在字符串上下文中使用变量会导致
perl
缓存字符串。你可能会发现
Devel::Peek
有助于理解引擎盖下发生的事情。版本中有太多这些奇怪的问题影响到用户的程序,所以我尝试从不使用它。Yikes。。。这似乎是一种引入细微缺陷的可怕方式。还是。。。也很酷:)