2013-02-15 58 views
0

后续代码会吃@populations的perl的foreach吃所有的数组内容

@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的错误?

回答

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;

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循环使用$_含蓄:

更明确地说,你的代码是等价的。

+0

谢谢你们! – user1143669 2013-02-15 22:10:22