我正在使用论坛上的example测试perl脚本。我拿了样本数据并将其放在一个单独的文件中,并使用open来尝试这种方式。
我不明白为什么我会得到undef。我收到了消息:
在./h.pl第15行第4行的连接或字符串中使用未初始化的值。
#!/usr/local/bin/perl
use warnings;
use strict;
use Data::Dumper;
use Text::CSV_XS;
open my $fh, '<', 't.out' or die "Unable to open: $!";
my $csv = Text::CSV_XS->new( { sep_char => "\t" } );
my @list;
$csv->column_names ($csv->getline ($fh));
while ( my $hr = $csv->getline_hr($fh) ) {
push @list, $hr->{'Ball'};
}
print "@list\n";
print Dumper(\@list);
测试文件(t.out)
Camera Make Camera Model Text Ball Swing
a b c d e
f g h i j
k l m n o
$ od -cx t.out
0000000 C a m e r a M a k e \t C a m e
6143 656d 6172 4d20 6b61 0965 6143 656d
0000020 r a M o d e l \t T e x t \t B a
6172 4d20 646f 6c65 5409 7865 0974 6142
0000040 l l \t S w i n g \n a \t b \t c \t d
6c6c 5309 6977 676e 610a 6209 6309 6409
0000060 \t e \n f \t g \t h \t i \t j \n k \t l
6509 660a 6709 6809 6909 6a09 6b0a 6c09
0000100 \t m \t n \t o \n \0
6d09 6e09 6f09 000a
0000107
结果:
$VAR1 = [
undef,
undef,
undef
];
答案 0 :(得分:2)
如果$csv->getline_hr($fh)
返回未定义的值,如果您尝试打印列表Use of uninitialized value in join or string at ...
,则会收到警告“@list
”。
您可以使用一个简单的程序明确地测试它:
use strict;
use warnings;
my @list;
my $x = undef; # This is similar to what may happen in your program on the `push @list, @hr->{'Name'}` line
push @list, $x;
print "@list\n";
此外,如果您只是在进行调试,则可能需要use Data::Dumper
然后print Dumper(\@list)
,因为您不会收到任何警告,并且您将更清楚地了解存储的内容你的数据结构。
答案 1 :(得分:1)
正如其他人所提到的,@list
很可能永远不会有价值。如果$csv->getline_hr($fh)
第一次返回undef,您将永远不会将任何内容推送到@list
。
您可以做两件事:
@list
是否未初始化use warnings
pragma,不要包含未初始化的警告:以下是您可以进行测试的方法:
if (@list) {
print "List = " . @list . "\n";
}
else {
print "List has no values\n";
}
您可以将scalar @list
用作Igor Zinov'yev节目,但在这种情况下这并不是必需的,我认为简单if (@list)
更清晰。您也可以使用if (defined @list)
,这是非常明确的,但在过去几年中一直被劝阻。
如果这是临时的事情(只是看看你的代码是否有效),你可以放松使用strict:
no warnings qw(uninitialized);
print "@list\n"; #Now you won't get a warning if @list has no value
use warnings; #Turn the warnings back on. It helps you code better
一个轻微的词'o警告:在这种情况下,你的陈述不会打印任何东西,这可能会让你更加困惑。始终使用某种提示来确保打印内容:
print "\@list = @list\n";
当我打印出很多我稍后会删除的调试语句时,我更喜欢这个作为临时解决方案。实际上,我将为这些类型的消息创建一个特殊的debug
子例程:
use strict;
use warnings;
use constant DEBUG_LEVEL => 1; #0 = no debug messages 1 = debug messages
[...]
while (yadda, yadda, yadda) {
push @list, $hr->{Name};
}
debug (qq(\@list = ") . join "|", @list . qq("));
[...]
sub debug {
my $message = shift;
return if (not DEBUG_LEVEL);
no warnings qw(uninitialized);
print qq(DEBUG: $message\n);
use warnings; #Not really needed since the code block ends
return $message;
}
答案 2 :(得分:1)
在你提到的问题中,我也写了最后一行:
ETA:如果你要削减&amp;粘贴试试看,确保 选项卡在数据中继承。
您是否确保将标签复制/粘贴到文件't.out'
?
这个模块对于数据文件中的错误格式是相当无法容忍的。
<强>更新强>
请注意,'Ball '
等字段将被视为与'Ball'
不同。即如果你有额外的空格,那就会搞砸了。
您可以尝试解决的问题是将allow_whitespace => 1,
添加到$csv
对象的选项中。这将纠正输入文件中的任何细微的空格错误。
您还可以通过
打印标题键来检查格式错误print Dumper $csv->column_names();
答案 3 :(得分:0)
您的@list
数组似乎未定义。试一试:
if (scalar @list) {
print "@list\n";
}
如果您的while循环从未执行过,scalar @list
将返回0
,因为该数组为空。