Perl map功能不起作用

时间:2012-12-16 17:55:39

标签: perl paste filehandle initialization

我有一个问题。这个perl程序应该打开所有文件并将它们映射到一起,类似于unix系统中的paste命令。

my @files;
for (@fileList ? @fileList : qw(-)) {
open  $files[@files], '<', $_; #}
}
while (grep defined, (my @lines = map {scalar <$_>;} @files)) {
    chomp @lines;
    print join("\t", @lines), "\n";
}

问题是,当谈到两个不同的文件,如

One 
Two 
Three

Apple
Banana
Orange
Kiwi

它给我一个未初始化的错误。

Use of uninitialized value $lines[0] in chomp 
Use of uninitialized value $lines[0] in join 

同样的错误反之亦然,当文件是Apple,Banana ..和One two 3时。

提前谢谢

2 个答案:

答案 0 :(得分:3)

问题在于,由于您的文件长度不同,因此您的@lines数组中会出现一些未定义的值。你不能在while条件下过滤它们,但是你可以在循环中过滤它们:

while (grep defined, (my @lines = map {scalar <$_>;} @files)) {
    @lines = map defined($_) ? $_ : "", @lines;

这将使用空字符串替换未定义的值,删除这些值的所有uninitialized警告,同时保持标签正确对齐。

请注意,您的代码实际上是按照它的意图执行的,因为undef将字符串化为空字符串。这只是因为你有警告,你得到关于它的警告。但是,警告是一个非常好的主意,因此可以找到并正确修复此类错误。

您应该注意,除非您明确处理失败的案例,否则使用open而不检查其返回值并不是一个好主意。正确的方法是这样做:

open $files[@files], '<', $_ or die $!;

为简单起见,我们也可以使用

use autodie;

autodie模块将为关键函数调用产生致命错误,例如open

答案 1 :(得分:0)

如果您安装了Perl v5.10或更高版本(并且您真的应该,因为它现在已经五年了)那么您可以使用//(defined-or)运算符将空字符串替换为{ {1}}文件结束后。它还会在其操作数上强加标量上下文,因此不需要使用undef运算符。此外,您必须将scalar运算符替换为length,从而生成此代码

defined