Во-первых, лучше использовать регулярное выражение вместо индекса, так как вы можете настроить его на точный формат строки состояния, если решите быть строже, чем просто "подстрока существует"
Я бы предложил в качестве одного решения добавить второй флаг, чтобы пропустить содержимое блока, если это блок MaterializeU4, следующим образом:
# Read a constant definition block from a file handle.
# void return when there is no data left in the file.
# Empty return for skippable (Materialize4U) block!!!
# Otherwise return an array ref containing lines to in the block.
sub read_block {
my $fh = shift;
my @lines = ();
my $block_started = 0;
my $block_ignore = 0;
while (my $line = <$fh> ) {
if ($line =~ /^status.*?((MaterializeU4)?)/) {
$block_started = 1;
$block_ignore = 1 if $1;
}
last if $line =~ /^\s*$/ && $block_started;
push @lines, $line unless $block_ignore;
}
return \@lines if @lines || $block_started;
return;
}
Вот немного измененный пример, который я протестировал с помощью codepad.org:
Код:
use Data::Dumper;
my @all_lines = (
"s 1" ,"b 1" ,""
, "s MaterializeU4" ,"b 2" ,""
, "s 3" ,"b 3" ,""
);
while (@all_lines) {
my $block = read_block();
print Data::Dumper->Dump([$block]);
}
exit 0;
sub read_block {
my @lines = ();
my $block_started = 0;
my $block_ignore = 0;
while (my $line = shift @all_lines) {
if ($line =~ /^s .*?((MaterializeU4)?)/) {
$block_started = 1;
$block_ignore = 1 if $1;
}
last if $line =~ /^\s*$/ && $block_started;
push @lines, $line unless $block_ignore;
}
return \@lines if @lines || $block_started;
return;
}
выход
$VAR1 = [
's 1',
'b 1'
];
$VAR1 = [];
$VAR1 = [
's 3',
'b 3'
];