迭代哈希时的Perl警告



下面的代码给出了以下警告消息,这让我困惑了一段时间:Use of uninitialized value in join or string at ./mycode.pl line 666.,其中第666:print "@{n0->{$x}{$y}}n";行。注意,n是字符串数组散列的散列,如下所示:

n  = (
 x0 => {
   y0 => [ "foo00", "bar00" ]
   y1 => [ "foo01", "bar01" ]
   ...
 }
 x1 => {
   y0 => [ "foo10", "bar10" ]
   y1 => [ "foo11", "bar11" ]
   ...
 }
...
)

这是代码:

my $rn =%n;
for my $x (keys %$rn){
    print "$xn";
    for my $y (keys %{$rn->{$x}}){
        print "@{$rn->{$x}{$y}}n";
    }
}

我不明白Perl为什么要抱怨uninitialized values。从本质上讲,我预计元素必须有值,否则它们甚至不存在,因此不会出现在迭代中。此外,输出符合我的预期。

我在这里错过的关键是什么?我怎样才能摆脱它?

乍一看,您的代码似乎没有什么问题。因此,您的数据存在争议。

我建议使用Data::Dump(我的首选)或Data::Dumper这样的模块来检查您的数据。然后,您不仅可以更容易地确定哪个键有坏数据,还可以更轻松地确定哪个值。

如果你想做得更好,你甚至可以创建一个特殊的$SIG{__WARN__}处理程序,只在发现错误时输出附加信息。

use strict;
use warnings;
my %n = (
    x0 => {
        y0 => [ "foo00", "bar00" ],
        y1 => [ "foo01", "bar01" ],
    },
    x1 => {
        y0 => [ "foo10", undef ],
        y1 => [ "foo11", "bar11" ],
    },
);
my $rn = %n;
for my $x ( keys %$rn ) {
    print "$xn";
    for my $y ( keys %{ $rn->{$x} } ) {
        # Catch Warning and output additional info
        local $SIG{__WARN__} = sub {
            warn @_;   # Output regular warning info
            use Data::Dump;
            dd $x, $y, $rn->{$x}{$y};
        };
        print "@{$rn->{$x}{$y}}n";
    }
}

输出:

x1
foo11 bar11
Use of uninitialized value in join or string at b.pl line 24.
("x1", "y0", ["foo10", undef])
foo10 
x0
foo01 bar01
foo00 bar00

以下代码有效;看看代码中有什么不同。

use strict;
use warnings;
my %n = (
 x0 => {
   y0 => [ "foo00", "bar00" ],
   y1 => [ "foo01", "bar01" ]
 },
 x1 => {
   y0 => [ "foo10", "bar10" ],
   y1 => [ "foo11", "bar11" ]
 }
);
my $rn =%n;
for my $x (keys %$rn){
    print "$xn";
    for my $y (keys %{$rn->{$x}}){
        print "@{$rn->{$x}{$y}}n";
    }
}

也许你的数据并不是你想象的那样?添加一个use Data::Dumper; print Data::Dumper->new([$rn])->Useqq(1)->Terse(1)->Dump;,看看那里是否有什么线索。

您可以通过将其放在打印之前来跟踪哪些值特别触发了警告:

local $SIG{__WARN__} = sub { print "warning given when x is $x and y is $y: ", @_ };

也就是说,除非其中一个数组元素是未定义的,否则我根本无法得到你的警告,除非我将$"设置为undef(尽管你使用的是古老版本的perl,而我不是,所以这可能会有所不同。)如果事实上你正在更改$"(通常是一个空格字符),你应该避免在字符串中插入数组,而是显式地执行:

print join(" ", @{$rn->{$x}{$y}}), "n";

最新更新