【问题标题】:How can I emulate 'grep -B' functionality in Perl?如何在 Perl 中模拟“grep -B”功能?
【发布时间】:2011-11-26 15:16:01
【问题描述】:

我一直在寻找一种解决方案,该解决方案允许我搜索数组的行,如果匹配到字符串,则将该行和前 2 行推入一个数组。使用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);

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

感谢您的帮助!

【问题讨论】:

  • 这是很久以后的事,但对于未来的读者来说:related post

标签: regex perl grep


【解决方案1】:

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

获取匹配的索引:

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 更繁忙的解决方案!

【讨论】:

  • 这很棒!非常感谢您的解决方案和每一行的解释。
  • @Zaid 你可以把它缩减为... = map @RAWDATA[$_-2 .. $_], grep ...
  • @Zaid - 正如我在对 TLP 的回答的评论中指出的那样,他的方法有一个好处。对于一个非常大的文件,他的代码可以很容易地适应只扫描文件一次而不存储它 - 没有浪费两个 O(N) 内存来存储 @RAWDATA 并做两次工作遍历数据(一个用于将文件拆分为@RAWDATA 数组,另一个用于grep)。
  • @DVK :同意,尽管 OP 预先给了我一个可以使用的数组,所以我猜这不是真正的问题。
  • 我只是偶然发现了 Schwartzian 变换这个术语,它是 IMO 仅在排序上下文中使用的,这里没有做。装饰-排序-取消装饰。
【解决方案2】:

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

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;
}

【讨论】:

  • @DVK 实际上,他只扫描了一次数据。除非您将 map $RAWDATA[$_] 视为扫描之一。
  • 对不起,不完全是。我的意思是将原始文本拆分为@RAWDATA 作为额外的扫描(您的观点也是一种扫描,但它是 O(M),其中 M 是匹配数)。您的代码可以与<$filehandle>@RAWDATA 一起使用,因此可以轻松调整为只扫描一次超大文件。扎伊德的不能。一个额外的 ++ 主要好处是节省内存。
【解决方案3】:

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

【讨论】:

    猜你喜欢
    • 2017-12-26
    • 2010-09-14
    • 2012-01-13
    • 1970-01-01
    • 2021-04-29
    • 2018-07-19
    • 1970-01-01
    • 2022-11-22
    • 2018-07-29
    相关资源
    最近更新 更多