【问题标题】:File parsing using perl使用 perl 解析文件
【发布时间】:2016-07-31 08:59:26
【问题描述】:

我被困在中间,我需要帮助。

我有两个文件:

  • 文件 1:

总 X :
总计 :
总 z :
总时间:

文件 2:
4790351 4786929 3422 0
84860 84860 0 0
206626 206626 0 0
93902 93823 79 0

现在我想在第三个文件中这样输出

总X:4790351 4786929 3422 0
总年数:84860 84860 0 0
总z:206626 206626 0 0
总吨数:93902 93823 79 0

这是我下面尝试解析的代码:请帮助我获得所需的输出

while ( not eof $tata and not eof $outfh )
 {
   my @vals1 = split /":"/,<$tata>;


   my @vals2 = split /\s+/, <$outfh>;

   my @sum = join "\t", map { $vals1,$vals2[$_]} 0 .. $#vals2;

   printf $_ for @sum,"\n";

   }

【问题讨论】:

标签: perl parsing


【解决方案1】:
use strict;
use warnings; 
use 5.020;
use autodie;
use Data::Dumper;

open my $FILE1, "<", "file1.txt";
open my $FILE2, "<", "file2.txt";
open my $OUTFILE, ">", "results.txt";

my $first_line = <$FILE1>;
close $FILE1;

my @line_prefixes = split /\s*:\s*/, $first_line;

while (my $line = <$FILE2>) {
    print {$OUTFILE} "$line_prefixes[$. - 1]: $line";
}

close $FILE2;
close $OUTFILE;

$. 是文件中的当前行号(第一行$. 等于 1)。

示例运行:

/pperl_programs$ cat file1.txt
Total X : Total y : Total z : Total t :

~/pperl_programs$ cat file2.txt
4790351 4786929 3422 0
84860 84860 0 0
206626 206626 0 0
93902 93823 79 0

~/pperl_programs$ cat results.txt

~/pperl_programs$ perl myprog.pl

~/pperl_programs$ cat results.txt
Total X: 4790351 4786929 3422 0
Total y: 84860 84860 0 0
Total z: 206626 206626 0 0
Total t: 93902 93823 79 0
~/pperl_programs$ 

对于您更改的文件:

use strict;
use warnings; 
use 5.020;
use autodie;
use Data::Dumper;

open my $FILE1, "<", "file1.txt";
open my $FILE2, "<", "file2.txt";
open my $OUTFILE, ">", "results.txt";

chomp(my @line_prefixes = <$FILE1>);
close $FILE1;

while (my $line = <$FILE2>) {
    print {$OUTFILE} "$line_prefixes[$.-1] $line";
}

close $FILE2;
close $OUTFILE;

样本输出:

~/pperl_programs$ cat file1.txt
Total X :
Total y :
Total z :
Total t :

~/pperl_programs$ cat file2.txt
4790351 4786929 3422 0
84860 84860 0 0
206626 206626 0 0
93902 93823 79 0

~/pperl_programs$ cat results.txt

~/pperl_programs$ perl 1.pl

~/pperl_programs$ cat results.txt
Total X : 4790351 4786929 3422 0
Total y : 84860 84860 0 0
Total z : 206626 206626 0 0
Total t : 93902 93823 79 0

如果您的文件很大,您可能不想将整个第一个文件读入内存。如果是这种情况,您可以逐行读取每个文件:

use strict;
use warnings; 
use 5.020;
use autodie;
use Data::Dumper;

open my $FILE1, "<", "file1.txt";
open my $FILE2, "<", "file2.txt";
open my $OUTFILE, ">", "results.txt";

while (!eof($FILE1) and !eof($FILE2) ) {
    my $line_prefix = <$FILE1>;
    chomp $line_prefix;

    my $numbers_line = <$FILE2>;
    chomp $numbers_line;
    my @numbers = split /\s+/, $numbers_line;

    my $fifth_column = $numbers[1] / $numbers[0];
    say {$OUTFILE} "$line_prefix $numbers_line $fifth_column";
}

close $FILE1;
close $FILE2;
close $OUTFILE;

【讨论】:

  • 嗨螺柱...实际上文件1没有单行中的所有标签...。总x然后总y在新行等等......所以你的代码首先打印文件 1 的行直到第一次拆分
  • @Volverine,我为您的新输入文件添加了一个示例。
  • @stud ..谢谢它起作用了...我还有一个查询...假设我想将第 2 列的值除以第 3 列的值并将其打印在要添加的最后一列中(第 5 列)列)..我们该怎么做...例如 Total X : 4790351 4786929 3422 0 0.99 (休息也一样)。你也可以帮忙吗
  • @Volverine,Illegal division by zero。但一般来说,my @numbers = split /\s+/, $line; my $fifth_column = $numbers[1] / $numbers[2]; print {$OUTFILE} "$line_prefixes[$.-1] $line $fifth_column";
  • @stud 我的输出如下 Total Z : 2135943 2135943 0 0 Total Y : 420512 420512 0 0 Total X : 0 0 0 0 我们可以像下面这样排列输出 Total Z : 2135943 2135943 0 0 总 Y : 420512 420512 0 0 总 X : 0 0 0 0
【解决方案2】:

您的规范有一些松散的地方;例如 - 如果file2 中有更多行,那么file1 中有总标签怎么办?您希望忽略第一个输入文件中的空格吗?您是否希望输出文件中的空格特别如图所示? ...而且您真的不想计算任何总数??

我对这些问题中的大多数都假设“是”。我的解决方案是由第二个数据文件驱动的——这意味着如果有更多的总标签然后有数据行,它们将被忽略。这也意味着如果file2中有更多的数据行然后file1中有标签,程序将简单地弥补标签-No Label?

最后,以防万一您想在某个时候将这些数字相加,我已将 List::Util 中的 sum 函数包含在内,但对其进行了注释。

use v5.12;
use File::Slurp;
# use File::Util qw( sum );

my $file1 = "file1.txt";
my $file2 = "file2.txt";
my $file3 = "file3.txt";

open(my $outfh, '>', $file3) or die "$file3: $!";

my @vals1 = split /\s*:\s*\n/ , read_file($file1);
my @vals2 = read_file($file2);

while (my $line = shift @vals2) {
    chomp $line;
    # my $total = sum split(" ", $line);
    printf $outfh  "%s : %s\n" , shift @vals1 // "No Label?" , $line ;
}
#
# $ cat file3.txt
Total X : 4790351 4786929 3422 0
Total y : 84860 84860 0 0
Total z : 206626 206626 0 0
Total t : 93902 93823 79 0

【讨论】:

  • 两个文件中标签和数据的数量总是相等的
  • 那么显示的代码就可以正常工作了——它只需要// "No Label?" 来覆盖错误情况,所以不妨把它留在那里。
猜你喜欢
  • 2013-03-17
  • 2017-10-28
  • 2015-12-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-14
  • 2013-04-16
  • 1970-01-01
相关资源
最近更新 更多