如何在Perl中模拟'grep -B'功能?

时间:2011-11-25 19:17:50

标签: regex perl grep

我一直在寻找一种允许我搜索数组行的解决方案,如果匹配字符串,则将该行和前两行推入数组。看起来这很容易使用grep命令完成。但是,我无法让这个工作。这就是我所拥有的:

sub ipsearch {
    my $ip = $_[0];
    my @IPVSCONFIG =  grep (/\W+virtual\s$ip\s/, @RAWDATA);
}

是否可以在grep命令中添加“-B 2”语法?我已经尝试了这种语法的几种形式,但我无法让它起作用:

@IPVSCONFIG =  grep -B 2 (/\W+virtual\s$ip\s/, @RAWDATA);

如果可能,请告诉我,以及正确的语法应该是什么。如果您有任何其他建议,请告诉我。

感谢您的帮助!

3 个答案:

答案 0 :(得分:5)

诀窍是识别匹配发生的行,然后识别相关的索引:

获取匹配的索引:

my @matchedIndices = grep { $RAWDATA[$_] =~ /\W+virtual\s$ip\s/ } 2 .. $#RAWDATA;

获取指数:

my @wantedIndices  = map { ( $_-2 .. $_ ) } @matchedIndices;

采取数组切片:

my @IPVSCONFIG = @RAWDATA[ @wantedIndices ];

将它完全放在Schwartzian变换中:

my @IPVCONFIG = map  { @RAWDATA[$_-2..$_] }
                grep { $RAWDATA[$_] =~ /\W+virtual\s$ip\s/ }
                2 .. $#RAWDATA ;

绝对比传统的命令行grep -B 2更加繁忙!

答案 1 :(得分:3)

子程序的基本版本。我假设您想在完成后返回列表。未经测试。

sub ipsearch {
    my $ip = shift;
    my @IPVSCONFIG = (); # no matches should be empty list, not undef
    my @buffer = ()      # to avoid undef warnings
    for (@RAWDATA) {
        push @buffer, $_;
        shift @buffer if @buffer > 3;
        if (/\W+virtual\s$ip\s/) {
            push @IPVSCONFIG, @buffer;
            @buffer = ();
        }
    }
    return @IPVSCONFIG;
}

答案 2 :(得分:2)

您正在将grep程序/bin/grep与名为grepperldoc -f grep)的perl函数混合。虽然前者需要额外的参数,例如-B,但后者不会。