1

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

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.. 和一二三时。

先感谢您

4

2 回答 2

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.

于 2012-12-16T18:38:42.937 回答
0

如果您安装了 Perl v5.10 或更高版本(您确实应该安装,因为它现在已经有 5 年历史了),那么您可以使用//(defined-or) 运算符在文件末尾替换空字符串undef。它还将对其操作数施加标量上下文,因此无需使用scalar运算符。此外,您必须将length运算符替换为defined,从而生成此代码

while (grep length, (my @lines = map { <$_> // '' } @files)) {
    chomp @lines;
    print join("\t", @lines), "\n";
}
于 2012-12-17T22:12:09.063 回答