perl中的嵌套循环数组引用

时间:2014-11-04 14:21:38

标签: perl

我有2个文件,这种格式具有相同的行

例如

档案1

string1:string2:string3
string4:string6:string6
string7:string8:string9

file2的

string1:string2:string3
string4:string6:string6
string7:string8:string9

我必须对这些文件做一些工作,但我在写作的开始,所以首先我做了这个

foreach my $firstFileString(<FILE1>){
    my @firstArray = split(/:/,$firstFileString);
    foreach my $secondFileString(<FILE2>){
    my @secondArray = split(/:/,$secondFileString);
    print "$firstArray[0]\n";
    }
}
在继续执行该程序之前

,我在输出中遇到了此问题,在此行中print "$firstArray[0]\n";我总是string1 。我期待string1, string4,string7

怎么可能?

提前感谢。

2 个答案:

答案 0 :(得分:2)

您的程序会为string1 时间的每一行打印file2

当内循环退出,外循环继续读取file1的第二行时,文件句柄FILE2已经在文件末尾,所以没有什么可读的了并且永远不会再输入内循环。

解决此问题的最佳方法是在外部循环中打开file2 ,以便在您想要通读它时始终位于文件的开头。最好使用词法文件句柄($file1而不是FILE1)并使用while读取文件,该文件一次读取一行文件,而不是{{1} },它读取整个文件,然后遍历内存中的行。

foreach

<强>输出

use strict;
use warnings;
use 5.010;
use autodie;

open my $file1, '<', 'file1.txt';

while (my $line1 = <$file1>) {
  chomp $line1;
  my @fields1 = split /:/, $line1;

  open my $file2, '<', 'file2.txt';

  while (my $line2 = <$file2>) {
    chomp $line2;
    my @fields2 = split /:/, $line2;

    print "$fields1[0]\n";
  }
}

<强>更新

正如您所说,另一种方法是将整个string1 string1 string1 string4 string4 string4 string7 string7 string7 读入数组。这样你就不必多次重新打开和阅读文件了。

由于您将数据存储在内存中,因此您也可以将其分成字段,以便多次保存。这个程序显示了如何。 file2被读入数组file2,其中每个元素都是一个字段数组。

现在,内部循环所要做的就是将@file2设置为数组的每一行。它是一个数组引用,因此字段为$fields2$fields2->[0]等。

$fields2->[1]

答案 1 :(得分:2)

问题是,你第一次通过外循环读到FILE2。第二次通过外部循环,它位于文件的末尾,所以这段代码:

foreach my $secondFileString(<FILE2>){

什么都不做。如果您希望FILE2再次读取,您可以在循环中关闭并打开它,或者寻找

foreach my $firstFileString(<FILE1>){
    my @firstArray = split(/:/,$firstFileString);
    seek FILE2, 0, SEEK_SET;
    foreach my $secondFileString(<FILE2>){
    my @secondArray = split(/:/,$secondFileString);
    print "$firstArray[0]\n";
    }
}

虽然那个输出是

string1
string1
string1
string4
string4
string4
string7
string7
string7

因为你在内循环中打印,所以每件东西都会重复三次。也许你打算在迭代之前在外部循环中打印FILE2