perl帮助解决使用perl模块的错误消息

时间:2011-08-18 15:11:39

标签: perl

我正在使用论坛上的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
        ];

4 个答案:

答案 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

您可以做两件事:

  1. 您可以在打印之前测试@list是否未初始化
  2. 您可以放宽use warnings pragma,不要包含未初始化的警告:
  3. 以下是您可以进行测试的方法:

    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,因为该数组为空。