使用 grep,如何匹配一个模式并反转匹配另一个模式?

Fli*_*imm 11 grep

使用grep,我想选择与某个模式匹配但与另一个模式不匹配的所有行。我希望能够使用单个调用,grep以便我可以使用--after-context选项(或--before-context、 或--context)。

-v在这里不可行,因为它否定了我grep使用该-e选项传递的所有模式。

例子

我想寻找行匹配needle,忽略行匹配ignore me,有一行以下上下文。

这是我的输入文件:

one needle ignore me
two
three
four needle
five
Run Code Online (Sandbox Code Playgroud)

我想要的输出是:

four needle
five
Run Code Online (Sandbox Code Playgroud)

如您所见,这个幼稚的解决方案不起作用:

$ cat file | grep --after-context=1 needle | grep -v 'ignore me'
two
---
four needle
five
Run Code Online (Sandbox Code Playgroud)

Gil*_*il' 10

如果你有 GNU grep,你可以使用Perl 正则表达式,它有一个否定结构

grep -A1 -P '^(?!.*ignore me).*needle'
Run Code Online (Sandbox Code Playgroud)

如果您没有 GNU grep,则可以在 awk 中模拟其前后上下文选项

awk -v after=3 -v before=2 '
/needle/ && !/ignore me/ {
    for (i in h) {
        print h[i];
        delete h[i];
    }
    until = NR + after;
}
{
    if (NR <= until) print $0; else h[NR] = $0;
    delete h[NR-before];
}
END {exit !until}
'
Run Code Online (Sandbox Code Playgroud)


iru*_*var 8

您似乎正在使用 GNU 。使用 GNU grep,您可以传入--perl-regex标志以激活 PCRE,然后提供否定的前瞻断言,示例如下

grep --after-context=1 \
--perl-regex '^(?:(?!ignore me).)*needle(?:(?!ignore me).)*$' file.txt
four needle
five
Run Code Online (Sandbox Code Playgroud)

这里值得注意的主要的事情是,(?:(?!STRING).)*STRING因为[^CHAR]*CHAR