0

以下代码将吃掉@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 大师,但有几年的经验。

谁能告诉我为什么?它是perl的错误吗?

4

2 回答 2

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

于 2013-02-15T21:58:18.363 回答
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;.

于 2013-02-15T22:02:02.670 回答