如何在 while<> 中识别 n 个文件的第 n 行

How to identify nth lines of n files in while<>

我有一个代码可以添加所有文件中的所有向量。 可以有任意数量的输入文件。例如第一个输入文件是:

0.55        0       0.3335      1.2
0.212       0       2.2025      1

第二个是:

0.25        0       0.3333      1.0
0.1235      0       0.2454      1

我得到的是所有向量的总和,因此结果我得到一个向量 即:

1.13550     0       3.1147      4.2

但我正在尝试将第一个文件的第一个向量与第二个文件的第一个向量相加,依此类推。根据这个例子的结果,我应该得到 2 个向量。

现在我有这个:

use strict;
use warnings;

if ($ARGV[0] ne "vector1.dat"){
    die ("vector1.dat is necessary as first argument");
}

my @sum = 0;
my $dim = 0;

while (<>) {

    #Ignore blank lines, hashtags 
    #and lines starting with $
    if ($_ =~ /#/ || $_ =~ /^$/ || $_ =~ /^\s$/){
        next;
    }
    my @vectors = split(" ", $_);
    my $vector_length = @vectors;

    if ($dim eq 0) {
        $dim = $vector_length;
    } 
    else {
        if ($dim ne $vector_length) {
            die ("Vector dimensions do not match. : $!");
        }
    }
    for (my $i = 0; $i <= $#vectors; $i++) {
        $sum[$i] += $vectors[$i];
    }
}

$" = "\t\t";
print "\n --- \n @sum \n";

我需要的只是找出如何识别每个文件的第n行 并在记住的同时总结这些行的列值,可以有 n 个文件。 我在这里看到了类似问题的文件处理问题,但是 我没有在那里找到我的答案。 只是寻找一些建议和指导。卡在这上面了。

试试这个:

#!/usr/bin/perl
use strict;
use warnings;

if ($ARGV[0] ne "vector1.dat"){
    die ("vector1.dat is necessary as first argument");
}

my %sum;
my $dim = 0;
my $vector_length;
my $line_number;

while (<>) {

    #Ignore blank lines, hashtags
    #and lines starting with $
    if ($_ =~ /#/ || $_ =~ /^$/ || $_ =~ /^\s$/){
        next;
    }
    my @vectors = split(" ", $_);
    $vector_length = @vectors;

    if ($dim eq 0) {
        $dim = $vector_length;
    }
    else {
        if ($dim ne $vector_length) {
            die ("Vector dimensions do not match. : $!");
        }
    }
    for (my $i = 0; $i <= $#vectors; $i++) {
        $sum{$.}{$i} += $vectors[$i];
    }
    $line_number = $.;
    $. = 0 if eof;
}

$" = "\t\t";
for (my $line=1; $line<=$line_number; $line++)
{
    print $line;
    for (my $vector=0; $vector<$vector_length; $vector++)
    {
        print " " . $sum{$line}{$vector};
    }
    print "\n";
}

自己打开每个文件并使用 $. 变量知道您在哪一行(或自己计算文件数)。这是基本结构:

foreach my $file ( @files ) {
    open my $fh, '<', $file or die ...;
    while( <$fh> ) {
        chomp;
        $sum[ $. ] = ...;  # $. is the line number
        }
    }

如果你不喜欢$.,你可以使用它更长的名字。您必须打开 English(Perl 附带):

use English;
## use English qw( -no_match_vars );  # for v5.16 and earlier

foreach my $file ( @files ) {
    open my $fh, '<', $file or die ...;
    while( <$fh> ) {
        chomp;
        $sum[ $INPUT_LINE_NUMBER ] = ...;
        }
    }

或者,您可以自己数一数,如果文件中的矢量未按严格的行号排列(可能是因为注释或其他格式异常),这可能会很方便:

foreach my $file ( @files ) {
    open my $fh, '<', $file or die ...;
    my $line = -1;
    while( <$fh> ) {
        $line++;
        chomp;
        $sum[ $line ] = ...;
        }
    }

更难的方法是在每行末尾 which inspects eof 查看神奇的 ARGV 句柄是否正在查看新文件,如果是则重置 $.。这是一个有趣的技巧,但几乎没有人会理解它在做什么(甚至不会注意到它)。

对于问题的另一部分,我认为你做的向量求和是错误的,或者使用了令人困惑的变量名。一条线是一个向量,线中的数字是一个分量。二维数组将起作用。第一个索引是行号,第二个是组件索引:

while( <$fh> ) {
    chomp;
    ... skip unwanted lines
    my @components = split;
    ... various dimension checks
    foreach my $i ( 0 .. $#components ) {
        $sum[ $. ][ $i ] += $components[ $i ];
        }
    }

Data::Dumper module is handy for complex data structures. You can also see the perldsc (Perl Data Structures Cookbook) documentation. The $. variable is found in perlvar.

$.是最近读取的文件句柄的行号。 close(ARGV) if eof; 可用于重置文件之间的文件编号(如 eof 中所述)。 (注意:eof()eof 不同。)因此您现在有了行号。

您遇到的第二个问题是您将向量分量 ($vectors[$i]) 添加到向量 ($sum[$i])。您需要将矢量分量添加到矢量分量。从使用更合适的变量名开始。

这是我们得到的:

my @sum_vectors;
while (<>) {
   s/#.*//;          # Remove comments.
   next if /^\s*$/;  # Ignore blank lines.

   my @vector = split;

   if ($sum_vectors[$.] && @{ $sum_vectors[$.] } != @vector) {
      die("$ARGV:$.: Vector dimensions do not match\n");
   }

   for my $i (0..$#vector) {
      $sum_vectors[$.][$i] += $vector[$i];
   }
} continue {
   close(ARGV) if eof;  # Reset line numbers for each file.
}

另外两个错误已修复:

  • $! 使用时没有包含任何有意义的内容。
  • 您忽略了包含注释的行,即使它们也包含有效数据。