Perl警告:在连接或字符串中使用未初始化的值

时间:2014-11-06 17:27:43

标签: perl warnings dbi

我得到了:

"Use of uninitialized value in join or string at ./test_script.pl line 69, <fh> line 91."

创建此警告的代码位于:

# Write results of SQL execution to output file
if ($@) { print "\n DB Error : ", $@; exit; }
open(FH, ">$output_file") or 
        die "\n cannot write to the file $output_file. Check the file permissions";
while(my @row= $sth->fetchrow_array) {
      print FH join($delimiter, @row). "\n";
}

它来自“while”块中的“print ... join ....”行,但我不确定100%是由什么引起它以及如何纠正它。

$ delimiter先前初始化为$ delimiter =“|”并且@row从前一行的$ sth操作中获取其值。

这是关于@row值的“时间”问题,还是正在处理的实际SQL查询文件中的某些内容,如警告的“&lt; fh&gt;第91行”部分所示?关于如何避免警告的任何想法? 顺便说一句,脚本运行正常,它只是为每个获取的@row值生成一个警告,这会在大数据集拉动时产生大量警告......

1 个答案:

答案 0 :(得分:11)

@row可能包含一些具有未定义值的元素,可能是因为填充@row的数据库中的一个或多个列是NULL。可以模仿这种行为,同时仍然在一个简单的Perl单行中使用join,如下所示:

perl -we 'my @array = ("Hello",undef,"world!"); print join("|",@array) . "\n";'

将产生的输出是:

Use of uninitialized value $array[1] in join or string at -e line 1.
Hello||world!

发生这种情况的原因是因为join试图加入一个没有字符串化而没有从“未定义”升级到“已定义”的值。字符串化undef会产生此警告消息,提醒您可能正在做一些无意识且不正确的事情。

更简单的例子可能是:

$ perl -we 'my $scalar; print "$scalar\n";'
Use of uninitialized value $scalar in concatenation (.) or string at -e line 1.

同样,我们得到警告,因为我们将未定义的值插入到字符串中。插值会导致字符串化,并且未定义值的字符串化通常会发出警告,通知您可能犯了错误。

如果您不介意将undef静默升级为空字符串,则可以这样做:

print FH join( $delimiter, map { defined ? $_ : '' } @row ) . "\n";

在将@row交给join()之前预处理@row。对于$delimiter中的每个元素,如果元素具有未定义的值,则该值将替换为空字符串,该字符串已定义但在视觉上很安静。

另一种可能性是no warnings 'uninitialized';未定义。通过打印对其进行测试,如果情况确实如此,那么您需要采取的修复步骤就是确保它实际上包含一个值。

在严格的词汇范围中简单地静音警告也可以,但从哲学的角度来看,一种方法可以消除原因,另一种方法可以消除其中一种症状。其他地方描述的“join方法就是这样做的;会使警告静音。当你知道你正在做一些完美的事情时,你会这样做但是你也知道Perl会警告你,因为很多次它是这可能就是这样的情况;你可能会非常高兴只是让{{1}}内部发生未定义值的无声字符串化。如果是这样的话,请继续并警告警告。最重要的是事情就是你知道它意味着什么,验证是什么导致了它,然后做出明智的决定,该怎么做。