我正在编写一个小的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”行。 在当前输出文件的最后一行如下:
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
答案 0 :(得分:1)
我建议您应该缓冲输出
如果你将每一行推到一个数组而不是打印它,那么一旦看到#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/;
}
}
答案 1 :(得分: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
}
}