【问题标题】:Perl loop not workingPerl循环不起作用
【发布时间】:2012-07-10 08:31:51
【问题描述】:

我正在处理一个简单的循环,但它不起作用。我有 2 个文件,我根据一个共同的 id 进行比较。它有点工作,因为它只输出第一个结果和第一个结果!所以它不会遍历其余文件(或最后一个文件,因为输出包含第一个文件中的所有行)。它输出第一个文件中的所有行,但仅将第二个文件中的第一个结果附加到 outfile 中。这是我要澄清的代码:

use strict;
use warnings;

my $inputfile1 = shift || die "Give input & output!\n";
my $inputfile2 = shift || die "Give input & output!\n";
my $outputfile = shift || die "Give input!\n";

open my $INFILE1,  '<', $inputfile1 or die "In use / Not found :$!\n";
open my $INFILE2,  '<', $inputfile2 or die "In use / Not found :$!\n";
open my $OUTFILE,  '>', $outputfile or die "In use / Not found :$!\n";

while (<$INFILE1>) {
s/"//g;
my @elements = split /;/, $_;

    while (<$INFILE2>) {
        s/"//g;
        my @loopelements = split /;/, $_;

            if ($elements[11] eq $loopelements[0]){
                $elements[12] = $loopelements[1];
                $elements[13] = $loopelements[2];
                }
    }

my $output_line = join(";", @elements);
print $OUTFILE $output_line;
#print "\n"
}

close $INFILE1;
close $INFILE2;
close $OUTFILE;

exit 0;

我的第一次尝试是这段代码,它部分工作。为什么?:中途崩溃。当我检查输出文件时,它工作到大约一半并停止。不知道为什么!顺便说一句,我认为下面的效率较低,还是两者都有更好的选择?

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

open(INFILE1,$inputfile1) || die "Give input & output :$!\n";
open(INFILE2,$inputfile2) || die "Give input & output :$!\n";
open(OUTFILE_1,">$outputfile1") || die "Give input & output :$!\n";

$i = 0;
$j = 0;

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

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

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

      if ($elements[11] eq $loopelements[0]){
         $elements[12] = $loopelements[1];
         $elements[13] = $loopelements[2];
         $printen = 1;
         last;
        }

      $j = $j+1;
      }

  @elements = join(";",@elements);
  print "$i\r";
  if ($printen == 1) { print OUTFILE_1 "@elements"; };

  $i = $i+1;
  }
close(INFILE1);
close(INFILE2);
close(OUTFILE_1); 

那么有人可以指出我在顶部的代码中哪里出错了吗?

【问题讨论】:

    标签: perl


    【解决方案1】:
    1. 第一个文件的第一行在外循环的第一次迭代中被读取。

    2. 在第一次迭代期间,所有第二个文件的行都在内循环中读取。

    3. 然后外循环的第一次迭代结束。

    4. 现在,外部循环的第二次迭代出现了。是否还有第二个文件需要读取?没有。

    将问题分解为最简单的问题,旁边带有 cmets 的两行代码使程序每次都循环通过第二个文件的行:

    use warnings;
    
    my $inputfile1 = shift || die "Give input & output!\n";
    my $inputfile2 = shift || die "Give input & output!\n";
    
    open my $INFILE1,  '<', $inputfile1 or die "In use / Not found :$!\n";
    open my $INFILE2,  '<', $inputfile2 or die "In use / Not found :$!\n";
    
    my $infile2_pos = tell $INFILE2; # remember start position
    
    while (<$INFILE1>) {
    
      print;
    
      seek $INFILE2, $infile2_pos, 0; # seek the start position
    
      while (<$INFILE2>) {
        print;
      }
    }
    

    如果这太慢,我看到你可以做两件事:

    1. 在外循环中读取更大的文件(我想你知道为什么这会加快速度)。
    2. 最初将较小的文件读入数组,因此您不必在其上重复执行磁盘 I/O。

    我的意思是:

    open my $BIGFILE,  '<', $bigfile or die "In use / Not found :$!\n";
    open my $SMALLFILE,  '<', $smallfile or die "In use / Not found :$!\n";
    
    my @smallfile_array = <$SMALLFILE>;
    
    while (<$BIGFILE>) {
    
      print;
    
      foreach (@smallfile_array) {
        print;
      }
    }
    

    【讨论】:

    • 啊,好吧!谢谢你这样说。我如何让它循环遍历第一个文件中每一行的第二个文件?我已经尽我所能(perl 新手)。
    • 我猜我的代码块不清楚。看看那里的cmets。第一个注释旁边的行记住了 INFILE2 的起始位置,第二个将文件指针重置到该位置(“寻找”它)。
    • "我如何让它循环遍历第一个文件中的每一行的第二个文件?"也许通过阅读 ArjunShankar 为您提供的代码!
    • @ArjunShankar 在您编辑之前,整行代码都是一条注释,所以我认为这是为了澄清一些事情。我认为它现在正在工作..但它非常慢。毫无疑问,它与 csv 文件有关。我之前没有提到过这个,但是第二个文件有超过 300k 行。这会减慢速度吗?
    • @Nickname27 - 是的,这是一条评论,我曾提到您必须取消评论它才能进行修复。至于性能方面,我将进行另一个编辑。
    【解决方案2】:

    查看@ArjunShankar 帖子中的代码问题。我没有做同样的事情,而是发布另一种方法。

    use strict 
    open my $IFILE1,  '< myfile.csv' or die $!;
    open my $IFILE2,  '< myfile.csv' or die $!;
    
    my %File1 = map {s/"//g; (join '-',(split /,/)[0,2]),$_} <$IFILE1>;
    my %File2 = map {s/"//g; (join '-',(split /,/)[0,2]),$_} <$IFILE2>;
    
    foreach my $Key (keys %File1) {
        print "REQD-DETAILS" if exists $File2{$Key};
    }
    

    【讨论】:

      猜你喜欢
      • 2015-11-05
      • 1970-01-01
      • 1970-01-01
      • 2014-02-07
      • 2019-01-23
      • 2012-03-30
      • 2011-10-19
      • 2016-03-04
      • 2012-07-02
      相关资源
      最近更新 更多