2016-11-15 4 views
-1

Я пишу небольшую программу perl, где я проверяю шаблон #start и #end. Повестка дня - создать отдельный файл с линиями между шаблонами начала и конца. Это я могу сделать с ниже сценария.Замените последнюю строку, записанную в файл descritor

#!/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 

ожидается из файлов последняя строка должна быть

preline 
execute 
postline 

входного файла (testcases):

#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

* Важно * использовать '' строгое ''и' использовать предупреждения 'all'' в верхней части каждой программы Perl, которую вы пишете. Нет смысла указывать переменные с '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

Я думаю Бородины ответ путь (я просто не в состоянии комментировать пока).

Так общий алгоритм:

  • собрать полную запись, от стартовых маркеров до конца маркера
  • когда маркер конца достигнут, содержание записи процесса. В вашем случае:
    • найти последнюю непустую строку и окружить его с другими
    • печати нашла линию
    • выписывать файл для записи
  • повторить при необходимости

I не смог устоять и переписать решение Бородинса с помощью оператора триггера:

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 
    } 
}