perl foreach吃掉所有数组内容

时间:2013-02-15 21:51:14

标签: perl

以下代码将包含@populations中的内容

@populations=("EUR","AFR","ASN","AMR");
print @populations,"\n";  #will show EURAFRASNAMR
foreach (@populations)
{  
    $filepath="tmp.txt"; #whatever text file you like 
    open(FILE,"<$filepath");
    while(<FILE>)
    {   
    }   
}   
print @populations,"\n";   #will print nothing

如果改为

foreach $i (@populations)

那么阵列就不会被吃掉。

或者如果标记while循环,则不会吃掉数组。

我不是一个perl guru,但有几年的经验。

谁能告诉我为什么?它是perl的一个bug吗?

2 个答案:

答案 0 :(得分:6)

不是一个错误的错误,但它是一个疏忽的陷阱。您隐式将@populations的元素分配给$_变量,然后您正在将FILE文件句柄中的数据读入$_,覆盖@populations的内容}。

更明确地说,您的代码相当于:

@populations=("EUR","AFR","ASN","AMR");
print @populations,"\n";  #will show EURAFRASNAMR
foreach $_ (@populations)    # $_ becomes "aliased" to the element in @populations
{  
    $filepath="tmp.txt"; #whatever text file you like 
    open(FILE,"<$filepath");
    while(defined($_ = <FILE>))  # overwrites $_, and erases element in @populations
    {   
    }   
}   
print @populations,"\n";   #will print nothing

您找到了一个很好的解决方法,即避免在$_循环中隐式使用for

答案 1 :(得分:5)

while (<$fh>) { ... }

替换为

while (defined($_ = <$fh>)) { ... }

这就是$_中可读取的值的原因。问题在于,$_当前是@populations元素的别名。

正如您所说,您可以使用

来避免这个问题
for my $population (@populations) {  
   ...
   while (<FILE>) { ... $_ ... }
   ...
}

但是仍然可以从调用子中删除$_。以下是两个更强大的修复程序:

for (@populations) {  # Or: for my $population (@populations) {  
   ...
   while (my $line = <FILE>) { ... $line ... }
   ...
}   

for (@populations) {  # Or: for my $population (@populations) {  
   ...
   while (local $_ = <FILE>) { ... $_ ... }
   ...
}

出于完全相同的原因,您不应将全局变量用于文件句柄。

$filepath="tmp.txt"; #whatever text file you like 
open(FILE,"<$filepath");
<FILE>

应该是

my $filepath="tmp.txt";
open(my $FILE, "<", $filepath) or die $!;
<$fh>

顺便说一句,请始终使用use strict; use warnings;