我得到了:
"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值生成一个警告,这会在大数据集拉动时产生大量警告......
答案 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}}内部发生未定义值的无声字符串化。如果是这样的话,请继续并警告警告。最重要的是事情就是你知道它意味着什么,验证是什么导致了它,然后做出明智的决定,该怎么做。