同时和foreach互动

时间:2014-08-26 12:04:26

标签: arrays perl foreach while-loop

我与foreach循环以及我不太了解的while进行了不受欢迎的互动。我有一个正常的for循环,然后是一个foreach循环通过一个数组。我用两者创建一个字符串(表示文件名),然后打开文件并阅读它。

我使用的代码在这里:

@array=(1,2);
for($y=0;$y<2;$y++)
{
    foreach(@array)
    {
        print "@array\n";
        $name="/Users/jorge/$_\_vs_$y\.txt";
        print "$name\n";
        open(INFILE,"$name") or die "Can't open files!\n";
        while(<INFILE>)
        {
            $line=$_;
        }
    }
}

,输出为:

array: 1 2
/Users/jorge/1_vs_0.txt
array:  2
/Users/jorge/2_vs_0.txt
array:  
/Users/jorge/_vs_1.txt

如果我删除了:

,似乎某种方式while循环缩短了我的数组
while(<INFILE>)

如果我改变了foreach,它的工作也是有意的:

foreach $tmp (@array)

并使用$ tmp而不是$ _,它也按预期工作,输出如下:

array: 1 2
/Users/jorge/1_vs_0.txt
array: 1 2
/Users/jorge/2_vs_0.txt
array: 1 2
/Users/jorge/1_vs_1.txt
array: 1 2
/Users/jorge/2_vs_1.txt
array: 1 2
/Users/jorge/1_vs_2.txt

2 个答案:

答案 0 :(得分:3)

您在两个嵌套循环上使用$_作为循环控制变量。相反,你应该为每个循环赋予自己的变量。

内循环不仅改变了外循环的控制变量的值,而且还改变了循环的实际数组。这是因为Perl的for / foreach 中的循环控制变量别名数组的元素,所以当<INFILE>构造时将一行读入$_,它会用该行覆盖@array的当前元素。当while循环完成读取文件后,$_将从最后<INFILE>出现为未定义,这意味着@array中最近处理的元素将始终未定义你回到foreach循环的顶部。

您还应该使用my声明变量,使用词法标量而不是裸字作为文件句柄,并使用open的三参数版本,所以我&#39;我们也在下面做了这些改变。但是,缩小数组问题的解决方案只是对两个循环中的至少一个使用显式变量而不是默认$_

my @array = (1, 2);
for (my $y = 0; $y < 2; $y++)
{
  foreach my $x (@array)   # using $x instead of $_
  {
    print "@array\n";
    my $name = "/Users/jorge/${x}_vs_$y.txt";  
    print "$name\n";
    open my $infile, '<', $name or die "$0: can't open file '$name': $!\n";
    while (my $line = <$infile>)   # using $line instead of $_
    {
        # do something with $line here
    }
  }
}

答案 1 :(得分:1)

您的while循环会覆盖数组内容,因为它使用的$_@array元素的别名。

最好在使用while

读取文件时使用词法(my)变量
    while (my $line = <INFILE>) {

        # ..
    }