下面的代码给出了以下警告消息,这让我困惑了一段时间: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";