Извлечение определенных строк с помощью 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 );
Другие вопросы по тегам