2012-12-16 105 views
1

我有問題。這個perl程序應該打開所有文件並將它們映射到一起,類似於在unix系統中粘貼命令。Perl映射函數不起作用

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 

同樣的錯誤反之亦然,當文件是蘋果,香蕉..和一個兩個三。

預先感謝您

+0

@TLP:它不是未定義(數組是從不未定義)和參照元素之後,最後也正是代碼的設計要做 – ysth

+1

標題有誤導性。 '地圖'完美無瑕。該錯誤在您的代碼中。 – mpe

回答

3

的問題是,由於您的文件有不同的長度,你會得到你的@lines陣列一些不確定的數值。你不能篩選出來的,而條件,但你可以事後篩選出來,內環路:

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

這將用空字符串替換未定義的值,刪除任何uninitialized警告這些值,同時保持你的標籤正確對齊。

請注意,您的代碼實際上是做它意味着要做的事情,因爲undef將字符串化爲空字符串。這只是因爲你有警告,你會得到有關它的警告。不過,這是一個非常好的主意,因此可以找到並修正錯誤,例如這樣的錯誤。

您應該注意,使用open而不檢查其返回值不是一個好主意,除非您明確處理失敗的案例。正確的方法是做到這一點:

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

爲了簡化人們也可以使用

use autodie; 

autodie模塊關鍵函數調用,如open將產生致命錯誤。

0

如果您安裝了Perl v5.10或更高版本(並且確實應該,因爲它現在已經五年了),那麼您可以使用//(定義或運算符)在結束後用空字符串代替undef的文件。它也會在其操作數上施加標量上下文,所以不需要使用運算符scalar。此外,您必須替換length運營商defined,造成這種代碼

while (grep length, (my @lines = map { <$_> // '' } @files)) { 
    chomp @lines; 
    print join("\t", @lines), "\n"; 
}