(Perl) 在地图中使用未初始化的值 $_

(Perl) Use of uninitialized value $_ in map

我正在尝试使用以下代码将查询结果导出到 CSV 文件:

while (my $query_result = $query_select->fetchrow_arrayref) {       
print $fh join (',', map {s{"}{""}g; "=\"$_\"";} @$query_result), "\n";
}

并收到这些警告:

  1. 在连接 (.) 或字符串中使用未初始化的值 $_
  2. 在替换中使用未初始化的值 $_ (s///)

因为有些记录中有NULL值。

如何将代码中的undefined值替换为空字符串

谢谢。

不要试图破解您自己的版本,使用适当的 CSV 模块,例如 Text::CSV 来做到这一点。例如:

use strict;
use warnings;

use Text::CSV;

my $csv = Text::CSV->new( { 
    binary => 1,
    eol => $/, 
} );

...

$csv->print(*STDOUT, $query_result);

为什么不让 mysql 使用 SELECT 处理它.... INTO OUTFILE

这是一个示例(来自 mysql 文档),它以许多程序使用的逗号分隔值 (CSV) 格式生成文件:

SELECT a,b,a+b INTO OUTFILE '/tmp/result.txt'
  FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"'
  LINES TERMINATED BY '\n'
  FROM test_table;

https://dev.mysql.com/doc/refman/5.6/en/select-into.html

有几种方法可以做到这一点,具体取决于您希望何时进行。

1:地图内。
Map 将评估给定块的全部内容,因此如果 $_ 为空,您可以将其设为空字符串。

print $fh join (',', map {$_='' if (!defined $_); s{"}{""}g; "=\"$_\"";} @$query_result), "\n";

2:我将采取的方法是确保从数据库中获取值时不为空。我能想到的每个 RDBMS 都有一个合并函数,该函数 returns 列表中的第一个非空值。

SELECT coalesce(a,''),coalesce(b,''),coalesce(c+d,'')...

将确保您不会得到空值。

say join " , ", map { s{"}{""}g; "\"$_\"" ; }  
 @{["stuff", undef, "nonsense", undef, "\""]} ;

重现您的错误:

Use of uninitialized value $_ in substitution (s///) at (eval 644) line 10.
Use of uninitialized value $_ in concatenation (.) or string at (eval 644) line 10.
Use of uninitialized value $_ in substitution (s///) at (eval 644) line 10.
Use of uninitialized value $_ in concatenation (.) or string at (eval 644) line 10.

要修复它,您只需使用 map 两次到 "pre-munge" 列表,将 undefs 转换为其他内容:

say join " , ", map { s{"}{""}g; "\"$_\"" ; } (
     map { $_="NA" if (not defined $_) ; $_ } 
     @{["stuff", undef, "nonsense", undef, "\""]} ) ;

输出:

"stuff" , "NA" , "nonsense" , "NA" , """"

有点难看(从 re.pl 剪切和粘贴)但你明白了。

说到 "pre-munging",您的 $query_select-> 调用是否可以通过某种方式在查询过程中做到这一点?更改查询可能会避免该级别的问题(e.g. with for (@queryrow) {$_ = 'NA' unless defined}; 或其他)。

$=$//'';等同于$=' ' 除非定义 $;

print $fh join (',', map {$_=$_//'';s{"}{""}g; ;"=\"$_\""} @{$query_result}), "\n";