使用Perl提取特定行

时间:2011-12-08 18:31:45

标签: perl line-processing

我正在编写一个perl程序来提取我匹配的两个模式之间的行。例如,下面的文本文件有6行。我正在匹配负载均衡器并结束。我想得到介于两者之间的4条线。

**load balancer** 
new 
old
good
bad
**end**

我的问题是如何在负载均衡器之间提取行并结束到数组中。任何帮助是极大的赞赏。

4 个答案:

答案 0 :(得分:7)

您可以使用flip-flop operator告诉您何时在标记之间。它还将包括实际标记,因此您需要从数据集合中除外。

请注意,如果您有多个记录,这会将所有记录混合在一起,所以如果您需要以某种方式存储和重置@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

答案 1 :(得分:2)

您可以使用flip-flop operator

此外,您还可以使用触发器的返回值来过滤掉边界线。返回值是一个序列号(从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

答案 2 :(得分:0)

如果您更喜欢命令行变体:

perl -ne 'print if m{\*load balancer\*}..m{\*end\*} and !m{\*load|\*end}' file

答案 3 :(得分:0)

对于这样的文件,我经常使用记录分隔符($/$RS来自English)进行更改

use English qw<$RS>;
local $RS = "\nend\n";

my $record = <$open_handle>;

当你chomp时,你就摆脱了那条线。

chomp( $record );