更新文件第一列的值并继续追加n次

时间:2017-03-28 17:24:43

标签: perl file append add

我正在寻找一种更好的方法来在文件的第一列上添加2内容,并继续追加n次。这可以是一个单线程序。

输入文件(sparc_test.export,它在实际文件中超过3000行):

20000 cmp_top.iop.sparc0.exu.alu.byp_alu_rcc_data_e[6]
20000 cmp_top.iop.sparc0.exu.alu.byp_alu_rs3_data_e[51]
20000 cmp_top.iop.sparc0.exu.alu.byp_alu_rs1_data_e[3]
20000 cmp_top.iop.sparc0.exu.alu.shft_alu_shift_out_e[18]
20000 cmp_top.iop.sparc0.exu.alu.byp_alu_rs3_data_e[17]
20000 cmp_top.iop.sparc0.exu.alu.byp_alu_rs1_data_e[43]

预期的输出文件(让我们说它运行3次):

20000 cmp_top.iop.sparc0.exu.alu.byp_alu_rcc_data_e[6]
20000 cmp_top.iop.sparc0.exu.alu.byp_alu_rs3_data_e[51]
20000 cmp_top.iop.sparc0.exu.alu.byp_alu_rs1_data_e[3]
20000 cmp_top.iop.sparc0.exu.alu.shft_alu_shift_out_e[18]
20000 cmp_top.iop.sparc0.exu.alu.byp_alu_rs3_data_e[17]
20000 cmp_top.iop.sparc0.exu.alu.byp_alu_rs1_data_e[43]
20002 cmp_top.iop.sparc0.exu.alu.byp_alu_rcc_data_e[6]
20002 cmp_top.iop.sparc0.exu.alu.byp_alu_rs3_data_e[51]
20002 cmp_top.iop.sparc0.exu.alu.byp_alu_rs1_data_e[3]
20002 cmp_top.iop.sparc0.exu.alu.shft_alu_shift_out_e[18]
20002 cmp_top.iop.sparc0.exu.alu.byp_alu_rs3_data_e[17]
20002 cmp_top.iop.sparc0.exu.alu.byp_alu_rs1_data_e[43]
20004 cmp_top.iop.sparc0.exu.alu.byp_alu_rcc_data_e[6]
20004 cmp_top.iop.sparc0.exu.alu.byp_alu_rs3_data_e[51]
20004 cmp_top.iop.sparc0.exu.alu.byp_alu_rs1_data_e[3]
20004 cmp_top.iop.sparc0.exu.alu.shft_alu_shift_out_e[18]
20004 cmp_top.iop.sparc0.exu.alu.byp_alu_rs3_data_e[17]
20004 cmp_top.iop.sparc0.exu.alu.byp_alu_rs1_data_e[43]

在第一列中添加2的单行perl代码是:

perl -pe 's/(\d+)/$1 + 2/e' sparc_export.test

所以,我使用了这段代码并追加(<<<<<<<<<<<<<<<<<<<<<<<<<<任何帮助表示赞赏。

我的perl代码(test.pl)

#!/usr/bin/perl 

use strict;
use warnings;
my $fin;
my $foutput;

for (my $i=0; $i < 3; $i++) {
            open $fin, '<', 'sparc_export.test' or die "Can't open file: $!";
            open $fout, '>>', 'sparc_export.test.out' or die "Can't open file: $!";
            while (<$fin>) {
                s/(\d+)/$1 + 2/e;
                print $fout $_;
            }
            close $fout;
            close $fin;
            rename 'sparc_export.test.out', 'sparc_export.test' or die "Failed to rename: $!";
            system $bin, @args;
}

1 个答案:

答案 0 :(得分:1)

唯一缺少的是您不先复制输入文件。 (好吧,为什么C-style for loop?)

您也可以避免额外的文件操作 - 读入数组并使用它。

use warnings;
use strict;

my $infile = 'sparc_export.test';
open my $fh, '<', $infile or die "Can't open $infile: $!";
my @lines = <$fh>;

my $outfile = 'sparc_export.test.out';
open    $fh, '>>', $outfile or die "Can't open for append $outfile: $!";

print $fh $_ for @lines;  # copy the original first

for my $i (1..3) 
{
    s/^\s*(\d+)/$1+2/e for @lines;  # changes @lines in place  

    print $fh $_ for @lines;
}
close $fh;
# now overwrite source

或者在内存中完成所有操作并更新原始文件一次,因为文件太小了。使用Path::Tiny

use warnings;
use strict;
use Path::Tiny;

my @lines = path('sparc_export.test')->lines;

my @all_lines = @lines;   

push @all_lines, map { s/(\d+)/$1+100/e; $_ } @lines  for 1..3;

path('sparc_export.test')->append( {truncate => 1}, @all_lines );

带有append选项的truncate会附加替换内容。

或者

my @lines = path('sparc_export.test')->lines;

my @new_lines = map { 
    map { s/(\d+)/$1+100/e; $_ } @lines 
} 1..3;

path('sparc_export.test')->append( @new_lines );

除非是特定要求,否则我认为没有更好的单线,