2016-11-15 82 views
-1

我正在写一个小的perl程序,我正在检查#start和#end的模式。议程是用开始和结束模式之间的线创建一个单独的文件。这我可以用下面的脚本来做。替换写入文件描述符的最后一行

#!/usr/bin/perl 

    open(INFILE,"<","testcases") || die "Can't open file: $!"; 
    my $binary; 
    my $tccounter=1; 

    while(<INFILE>) 
    { 
    if(/^#start/i) 
     { 
     open(OUTFILE,">",$tccounter."_case.sh") || die "Can't open file: $!"; 
     print "start of the script\n"; 
     next; 
     } 
    elsif(/^#end/i) 
     { 

     ################################ 
     # Want to replace the previously 
     # written line here with some 
     # addtional customized lines 
     ################################ 

     close(OUTFILE); 
     $tccounter++; 
     print "End of the script\n"; 
     print "last line for this testcase is \n $binary\n"; 
     next; 
     } 
    else 
     { 
     $binary=$_ unless(/^\s*$/); 
     print OUTFILE $_; 
     } 
    } 

但我还需要的是为确定被写入到文件的最后一行,然后替换一些自定义的数据,额外的线。 例如,在我的情况下,所有文件的最后一行是执行的。 我想在所有输出文件中替换“execute”行。 在电流输出文件的最后一行如下:

execute 

有望走出文件的最后一行应该是

preline 
execute 
postline 

输入文件(测试用例):

#start 
line1 
line 2 
execute 

#end 
#start 
line3 
line 4 
execute 
#end 
#start 
line5 
line 6 

execute 
#end 
#start 
line7 
line 8 

execute 

#end 
+2

*您必须*在您编写的每个Perl程序的顶部使用strict和'use warnings'all''。使用'my'来声明变量没有'use strict'就没有什么意义了。 – Borodin

回答

1

我建议你应该缓冲你的输出

如果你把每一行代替一个数组o f然后打印它,一旦看到#end标签,就很容易找到阵列中的最后一个非空白行并替换它

然后可以打开输出文件并将其打印到数组的内容

下面是一个未经考验例如

use strict; 
use warnings 'all'; 

open my $fh, "<", "testcases" or die "Can't open input file: $!"; 

my $n; 
my $i; 
my $print; 
my @buff; 

while (<$fh>) { 

    if (/^#start/i) { 

     @buff =(); 
     $i = undef; 
     $print = 1; 

     print "start of the script\n"; 
    } 
    elsif (/^#end/i) { 

     my $file = ++$n . "_case.sh"; 
     $print = 0; 

     unless (defined $i) { 
      warn "No data found in block $n"; 
      next; 
     } 

     splice @buff, $i, 1, "preline\n", $buff[$i], "postline\n"; 

     open my $fh, ">", $file or die qq{Can't open "$file" for output: $!}; 
     print $fh @buff; 
     close $fh; 

     print "End of the script\n"; 
    } 
    elsif ($print) { 

     push @buff, $_; 
     $i = $#buff if /\S/; 
    } 
} 
0

我觉得Borodins答案是去(我只是无法尚未就此发表评论)的方式。

所以一般的算法是:

  • 收集完整的记录,从开始标记结束标记
  • 一旦达到结束标志,过程记录的内容。你的情况:
    • 找到最后一个非空行,并与他人围绕着它
    • 打印找到的行
    • 需要

    我写出来的文件记录

  • 重复使用触发器操作员无法抗拒并重写鲍罗丁解决方案:

    use strict; 
    use warnings; 
    open(my $in,'<','in.file') || die "Can't open file: $!"; 
    my ($cnt,@rec); 
    while(<$in>) { 
        push(@rec,$_) if /^#start/i .. /^#end/i; # collect record lines (using flipflop operator) 
        if(/^#end/i) { # end of record reached? 
         next if @rec <= 2; # ignore empty records 
    
         # determine index of last nonempty line 
         my ($lci) = grep {$rec[$_]=~/\S/} reverse (1..$#rec-1); # ...except markers 
    
         printf "last line for this testcase is \n%s\n", # print find 
          splice @rec, $lci, 1, ("preline\n",$rec[$lci],"postline\n"); # surround with pre&post 
    
         # write out result 
         open(my $out,'>',++$cnt.'_case.sh') || die "Can't open file: $!"; 
         $out->print(@rec[1..$#rec-1]); # ...except markers 
         $out->close; 
    
         @rec=(); # empty record for next use 
        } 
    }