【问题标题】:Update a value of the first column of a file and keep appending n times更新文件第一列的值并继续追加 n 次
【发布时间】:2017-08-21 21:48:40
【问题描述】:

我正在寻找一种更好的方法来在文件第一列的内容上添加 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;
}

【问题讨论】:

    标签: perl file append add


    【解决方案1】:

    唯一缺少的部分是您没有先复制输入文件。 (嗯,为什么是 C 风格的 for 循环?)

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

    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 );
    

    appendtruncate 选项追加替换内容。

    或者

    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 );
    

    除非有特殊要求,否则我认为使用单线没有什么比这更好的了。

    【讨论】:

    • 感谢您的回复,但我收到了一个语法错误:第 11 行,靠近“打开”全局符号“$outfile”需要在 ./sparc_extract.pl 第 11 行显示包名称。执行 . /sparc_extract.pl 由于编译错误而中止。
    • 我通过添加“;”修复了错误在“sparc_export.test.out”之后。
    • @JaeyoungPark 抱歉打错了,感谢您发现并告诉我:)
    猜你喜欢
    • 2012-05-27
    • 1970-01-01
    • 2020-10-14
    • 2014-12-13
    • 1970-01-01
    • 2021-04-02
    • 2015-04-16
    • 1970-01-01
    • 2015-03-20
    相关资源
    最近更新 更多