Извлечение определенных строк с помощью Perl
Я пишу Perl-программу для извлечения строк, которые находятся между двумя шаблонами, которые я сопоставляю. например, приведенный ниже текстовый файл имеет 6 строк. Я сопоставляю балансировщик нагрузки и конец. Я хочу получить 4 строки, которые находятся между ними.
**load balancer**
new
old
good
bad
**end**
Мой вопрос: как вы извлекаете строки между балансировщиком нагрузки и заканчиваете массивом. Любая помощь с благодарностью.
4 ответа
Вы можете использовать оператор триггера.
Кроме того, вы также можете использовать возвращаемое значение триггера, чтобы отфильтровать граничные линии. Возвращаемое значение представляет собой порядковый номер (начиная с 1), а последний номер имеет строку E0
добавлен к нему.
# Define the marker regexes separately, cuz they're ugly and it's easier
# to read them outside the logic of the loop.
my $start_marker = qr{^ \s* \*\*load \s balancer\*\* \s* $}x;
my $end_marker = qr{^ \s* \*\*end\*\* \s* $}x;
while( <DATA> ) {
# False until the first regex is true.
# Then it's true until the second regex is true.
next unless my $range = /$start_marker/ .. /$end_marker/;
# Flip-flop likes to work with $_, but it's bad form to
# continue to use $_
my $line = $_;
print $line if $range !~ /^1$|E/;
}
__END__
foo
bar
**load balancer**
new
old
good
bad
**end**
baz
biff
Выходы:
new
old
good
bad
Вы можете использовать оператор триггера, чтобы сказать вам, когда вы находитесь между маркерами. Он также будет включать в себя фактические маркеры, поэтому вам нужно будет исключить их из сбора данных.
Обратите внимание, что это объединит все записи, если их несколько, поэтому, если вам нужно, вам нужно сохранить и сбросить @array
как-то.
use strict;
use warnings;
my @array;
while (<DATA>) {
if (/^load balancer$/ .. /^end$/) {
push @array, $_ unless /^(load balancer|end)$/;
}
}
print @array;
__DATA__
load balancer
new
old
good
bad
end
Если вы предпочитаете вариант командной строки:
perl -ne 'print if m{\*load balancer\*}..m{\*end\*} and !m{\*load|\*end}' file
Для таких файлов я часто использую изменение в Разделителе записей ($/
или же $RS
от English
)
use English qw<$RS>;
local $RS = "\nend\n";
my $record = <$open_handle>;
Когда ты chomp
это, вы избавляетесь от этой линии.
chomp( $record );