Perl 嵌套的foreach循环不工作

Perl 嵌套的foreach循环不工作,perl,loops,foreach,Perl,Loops,Foreach,它应该是一个简单的嵌套foreach循环,但它不起作用,而且真的开始让我恼火,因为我无法弄明白这一点!仍然是perl初学者,但我想我现在已经理解了这一点。有人能告诉我哪里出了问题吗?想法很简单:2个文件,1个小文件,1个大文件,小文件中有我想要的信息。两者都有唯一的id。比较并匹配id,并输出一个新的小文件,其中包含小文件中添加的信息 我有两段代码:一段没有严格要求,另一段有,但两者都不起作用。我知道使用严格限制,但我仍然很好奇为什么没有严格限制的也不起作用 没有严格规定: if ($#ARGV

它应该是一个简单的嵌套foreach循环,但它不起作用,而且真的开始让我恼火,因为我无法弄明白这一点!仍然是perl初学者,但我想我现在已经理解了这一点。有人能告诉我哪里出了问题吗?想法很简单:2个文件,1个小文件,1个大文件,小文件中有我想要的信息。两者都有唯一的id。比较并匹配id,并输出一个新的小文件,其中包含小文件中添加的信息

我有两段代码:一段没有严格要求,另一段有,但两者都不起作用。我知道使用严格限制,但我仍然很好奇为什么没有严格限制的也不起作用

没有严格规定:

if ($#ARGV != 2){
print "input_file1 input_file2 output_file\n";
exit;
} 

$inputfile1=$ARGV[0];  
$inputfile2=$ARGV[1]; 
$outputfile1=$ARGV[2]; 

open(INFILE1,$inputfile1) || die "No inputfile :$!\n";
open(INFILE2,$inputfile2) || die "No inputfile :$!\n";
open(OUTFILE_1,">$outputfile1") || die "No outputfile :$!\n";

$i = 0;
$j = 0;

@infile1=<INFILE1>;
@infile2=<INFILE2>;

foreach ( @infile1 ){
    @elements = split(";",$infile1[$i]);

    $id1 = $elements[3];
    print "1. $id1\n";

    $lat = $elements[5];
    $lon = $elements[6];

    $lat =~ s/,/./;
    $lon =~ s/,/./;

    print "2. $lat\n";
    print "3. $lon\n";

    foreach ( @infile2 ){
        @loopelements = split(";",$infile2[$j]);

        $id2 = $loopelements[4];

        print "4. $id2\n";

        if ($id1 == $id2){
        print OUTFILE_1 "$loopelements[0];$loopelements[1];$loopelements[2];$loopelements[3];$loopelements[4];$lat,$lon\n";
        };

        $j = $j+1;
        };

  @elements = join(";",@elements);  # add ';' to all elements
  #print "$i\r";
  $i = $i+1;
  }
close(INFILE1);
close(INFILE2);
close(OUTFILE_1);

您的“strict”实现会给您带来错误,因为它混淆了sigils($和@字符)指示变量是标量还是数组。在loop语句中,您正在将文件的每一行读入名为$infile1的标量中,但在下一行中,您正在尝试访问数组@infile1的元素。这些变量不相关,正如perl告诉您的,后者没有声明

“严格”实现的另一个问题是在循环中读取文件。这意味着对于嵌套循环,您将在外部循环的第一次迭代中读取文件2,对于所有后续迭代,内部循环将无法读取任何行

我错过了foreach/while问题,stevenl指出,即使修复了严格的问题,也只需一次迭代就可以得到foreach循环

我不确定你的非ICT脚本有什么问题

但我不会使用嵌套循环来处理两个文件。我将取消嵌套循环,因此大致如下所示:

my %cord;
while ( my $line = <$INFILE1> ) {
    my @elements = split /;/, $line;

    $cord{ $elements[3] } = "$elements[5],$elements[6]";
}

while ( my $line = <$INFILE2> ) {
    my @elements = split /;/, $line;

    if ( exists %coord{ $elements[4] } ) {
        print $OUTFILE "....;$cord{ $elements4 }\n";
    }
}
my%cord;
while(我的$line=){
my@elements=split/;/,$line;
$cord{$elements[3]}=“$elements[5],$elements[6]”;
}
while(我的$line=){
my@elements=split/;/,$line;
if(存在%coord{$elements[4]}){
打印$OUTFILE“…;$cord{$elements4}\n”;
}
}

由于对指示变量是标量还是数组的符号($和@字符)的混淆,您的“严格”实现会给您带来错误。在loop语句中,您正在将文件的每一行读入名为$infile1的标量中,但在下一行中,您正在尝试访问数组@infile1的元素。这些变量不相关,正如perl告诉您的,后者没有声明

“严格”实现的另一个问题是在循环中读取文件。这意味着对于嵌套循环,您将在外部循环的第一次迭代中读取文件2,对于所有后续迭代,内部循环将无法读取任何行

我错过了foreach/while问题,stevenl指出,即使修复了严格的问题,也只需一次迭代就可以得到foreach循环

我不确定你的非ICT脚本有什么问题

但我不会使用嵌套循环来处理两个文件。我将取消嵌套循环,因此大致如下所示:

my %cord;
while ( my $line = <$INFILE1> ) {
    my @elements = split /;/, $line;

    $cord{ $elements[3] } = "$elements[5],$elements[6]";
}

while ( my $line = <$INFILE2> ) {
    my @elements = split /;/, $line;

    if ( exists %coord{ $elements[4] } ) {
        print $OUTFILE "....;$cord{ $elements4 }\n";
    }
}
my%cord;
while(我的$line=){
my@elements=split/;/,$line;
$cord{$elements[3]}=“$elements[5],$elements[6]”;
}
while(我的$line=){
my@elements=split/;/,$line;
if(存在%coord{$elements[4]}){
打印$OUTFILE“…;$cord{$elements4}\n”;
}
}

我看不出非严格版本的问题在哪里。你遇到的问题是什么

严格版本的问题尤其表现在以下两行:

foreach ( my $infile1 = <$INFILE1> ){
    my @elements = split(";",$infile1[$i]);
  • 如果完全不使用数组索引,则可以简化阅读:

    foreach my $infile1 (@infile1) {
        my @elements = split ';', $infile1;
        ...
    }
    
  • 但是对于较大的文件,在开始时可能需要时间将整个文件拖到数组中。因此,最好在运行时对文件进行迭代:

    while (my $infile = <$INFILE1>) {
        ...
    }
    
    while(my$infle=){
    ...
    }
    
  • 注意最后一点应该是严格版本的外观。您需要一个
    while
    循环,而不是
    foreach
    循环,因为将
    赋值给标量意味着它将只返回下一行,只要文件中还有另一行,该行的计算结果就为true。(因此,
    foreach
    只会得到要循环的第一行。)


  • 我看不出非严格版本的问题在哪里。你遇到的问题是什么

    严格版本的问题尤其表现在以下两行:

    foreach ( my $infile1 = <$INFILE1> ){
        my @elements = split(";",$infile1[$i]);
    
  • 如果完全不使用数组索引,则可以简化阅读:

    foreach my $infile1 (@infile1) {
        my @elements = split ';', $infile1;
        ...
    }
    
  • 但是对于较大的文件,在开始时可能需要时间将整个文件拖到数组中。因此,最好在运行时对文件进行迭代:

    while (my $infile = <$INFILE1>) {
        ...
    }
    
    while(my$infle=){
    ...
    }
    
  • 注意最后一点应该是严格版本的外观。您需要一个
    while
    循环,而不是
    foreach
    循环,因为将
    赋值给标量意味着它将只返回下一行,只要文件中还有另一行,该行的计算结果就为true。(因此,
    foreach
    只会得到要循环的第一行。)


  • 在内部foreach循环运行之前,您不会重置$j。因此,第二次运行内部循环时,您正试图访问超出数组末尾的元素。这个错误在严格版本和非严格版本中都存在

    您根本不应该使用$i和$j;foreach的要点是它会自动为您获取每个元素。下面是在内部循环中正确使用foreach的示例:

    foreach my $line ( @infile2 ){
        @loopelements = split(";",$line);
    
        #...now do stuff as before
    }
    

    这会将@infle one的每个元素依次放入变量$line中,直到完成所有数组

    在内部foreach循环运行之前,不重置$j。因此,第二次运行内部循环时,您正试图