【问题标题】:Search two patterns on two consecutive lines and print n lines before the match在两个连续的行上搜索两个模式并在匹配前打印 n 行
【发布时间】:2017-05-27 22:01:00
【问题描述】:

我想使用 shell 命令 grep 或搜索匹配两个不同模式的两个连续行,例如匹配 line1:“abc”,匹配 line2:“def”。因此,对于以下文本,应该有一个匹配项:第 4 行和第 5 行。

1234
abc-noise
6789
abc-noise
def-noise
def-noise
1234

当我找到这样的匹配时,我想在匹配前打印它,包括 N 行。有任何想法吗?谢谢。

【问题讨论】:

  • 到目前为止你写了什么?
  • 您是否尝试过使用grepsed 或任何工具。发布您的研究成果
  • 没什么可展示的。我试过'grep -B1 def | grep -A1 abc' ,但后来我陷入了如何在比赛前获得 N 行的问题。其中 -B1 在匹配前输出 1 行,在匹配后输出 -A1 1 行
  • 不是真正的重复。棘手和不同的部分是我还需要在连续行匹配之前输出 N 行。

标签: linux bash shell grep


【解决方案1】:

如果您想在整个目录中递归搜索,请扩展 @Inian 的最佳答案:

find my_code_dir/ -type f  -name "*.py" -exec pcregrep -B2 -M  'except.*\n.*pass' {} +

此特定命令将查找包含 except 的行,紧随其后的是包含 pass 的行,但仅在 .py 文件中。

【讨论】:

    【解决方案2】:

    PCRE 模式下使用GNU grep,启用-P 标志,

    grep -ozP ".*abc.*\n.*def.*" file
    

    pcregrep 用于输入文件

    cat file
    1234
    abc-noise
    6789
    abc-noise
    def-noise
    def-noise
    1234
    noise-abc-noise
    noise-noise-def
    

    对于多行模式匹配,做

    pcregrep -M  'abc.*\n.*def' file 
    abc-noise
    def-noise
    noise-abc-noise
    noise-noise-def
    

    对于模式匹配之前的行,使用-B 标志,如GNU grep

    pcregrep -B2 -M  'abc.*\n.*def' file 
    abc-noise
    6789
    abc-noise
    def-noise
    def-noise
    1234
    noise-abc-noise
    noise-noise-def
    

    更多关于标志-M-B的信息来自man pcregrep页面,

    -M, --多行 允许模式匹配多于一行。给出此选项时,模式可能有用地包含文字换行符和内部 ^ 和 $ 字符的出现。成功匹配的输出可能包含不止一行,最后一行是 比赛结束。如果匹配的字符串以换行序列结束,则输出在该行的末尾结束。

    -B 数字,--before-context=数字 在每个匹配行之前输出上下文的行数。如果正在输出文件名和/或行号,则使用连字符分隔符 上下文行的冒号。在每组行之间输出一个包含“--”的行,除非它们实际上在输入中是连续的 文件。

    【讨论】:

    • 谢谢,那要求在比赛前打印N行呢?我之前用额外的标志 -B3 尝试了你的解决方案 3 行,但它不起作用。
    • @user2405602:你能用pcregrep吗?你能看看它是否安装了吗? which pcregrep?
    • ,是的,它已安装,但我使用您最初的建议找到了解决方案。两个在比赛前多得到 2 行你可以尝试:grep -ozP ".*\n.*\n.*abc.*\n.*def.*" file 所以只需为每个额外的行添加一个.*\n。不太优雅但很有效。
    • @user2405602:您不必发布这是一个答案。你可以接受我的回答(在我的回答左边打勾)让人们知道你已经解决了问题。另请参阅我的解决方案使用 pcregrep -
    【解决方案3】:
    #!/bin/bash
    a=''
    b=''
    while read c; do
            a=$b;
            b=$c;
            if [ `echo "$a" |grep "abc"` ] & [ `echo "$b" |grep "def"` ]; then
                    echo $a;
                    echo $b;
                    break;
            fi
    done
    

    发射:

    $./find2pat
    wegweg
    egwergwerg
    sdfabcerg
    rrheedef4
    

    输出:

    sdfabcerg
    rrheedef4
    

    【讨论】:

    • 谢谢,这里有同样的评论,那要求在比赛前打印N行呢?
    猜你喜欢
    • 2015-04-14
    • 1970-01-01
    • 2015-04-08
    • 1970-01-01
    • 2018-07-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多