打印找到的行之前/之后的 X 行

打印找到的行之前/之后的 X 行

我想在某个文件中搜索特定的字符串。如果找到了该字符串,我还想打印该行之前(或之后)的 X 行。

可以用 grep 或 awk 来做吗,或者我需要组合使用吗?

我想要类似的东西,但不是所有命中之前或之后的尾随/前导线,只有 X 条。

例如,如果我的输入如下所示:

line1 with a pattern
line2
line3
line4 with a pattern
line5
line6
line7 with a pattern
...

例如,我想搜索单词“pattern”,并输出该行 + 其后两行的行,但不输出紧跟该模式行的行。因此,所需的输出是:

line1 with a pattern
line3
line4 with a pattern
line6
line7 with a pattern
...

答案1

grep将为您完成此操作,使用选项-A(after) 和-B(before) 以及-C(context)。我经常使用的一个例子是:

   sudo lspci -vnn | grep -i net -A 12

因为这个命令匹配后会显示12行,其中包括用于控制网络(-i net)卡的驱动程序。一般来说,命令是:

  grep text_to_search -A n -B m file.extension

这将输出m匹配之前的行和n匹配之后的行。或者你可以使用

 grep text_to_search -C n file.extension

显示n找到的文本周围的总行数(匹配前一半,匹配后一半)。

答案2

在仔细研究了这个问题之后,我觉得我必须修改一下关于使用标准 GNU 工具而不使用脚本的可行性的评论。这可能是非常由于特殊情况,很难做到。

如果您不介意使用 awk,我可以提供以下解决方案。这个脚本context.awk仍然相当简洁:

{
    lines[NR] = $0
    if (dump[NR]) {
        print $0;
    if ($0 ~ Pattern) {
        if (NR-Delta in lines) {
            print "---"
            print lines[NR-Delta]
        }
        dump[NR+Delta] = 1
        print $0;
    }
    if (NR-Delta in lines) 
        delete lines [NR-Delta];
}

必须按如下方式调用它:

awk -v Delta=X -v Pattern=PATTERN -f context.awk sample.txt

其中X是所需的“上下文距离”,PATTERN搜索模式为。脚本尝试通过在---中间打印行来分隔文件中的多个模式上下文。因此,例如,以下sample.txt

line1
line2
line3 XXX
line4
line5
line6
line7 XXX
line8
line9
line10 XXX
line11

使用此调用

awk -v Delta=3 -v Pattern=XXX -f context.awk sample.txt

将产生以下输出

line3 XXX
line6
---
line4
line7 XXX
line10 XXX
---
line7 XXX
line10 XXX

答案3

以下sed命令似乎适用于您描述的情况,我将重述为:打印与我的模式匹配的行,不打印紧接着的下一行,还打印我的模式后两行的行,然后继续搜索模式匹配。

sed -n -e '/with a pattern/ {h;n;n;H;x;p}' file

它看起来有点丑,但通过添加额外的n(跳过行,移动到下一行)和H(通过将其附加到保持缓冲区来保留这一行)命令,您可以根据模式匹配构建任意的保持/跳过关系。

请注意,在匹配之后,我们首先使用 命令将匹配的行复制到保持缓冲区h。最后,我们用 交换保持和模式空间,x并使用 打印模式空间p。此时sed将继续逐行处理文件以寻找另一个匹配项。

sed可以找到命令的便捷参考这里

答案4

grep -A2 <pattern> file | grep -B1 <pattern> | grep -v "\-\-"对我有用:

user@box /tmp $ grep -A2 "with a pattern" test.txt | grep -B1 "with a pattern" | grep -v "\-\-"
line1 with a pattern
line3
line4 with a pattern
line6
line7 with a pattern

user@box /tmp $ cat test.txt 
line1 with a pattern
line2
line3
line4 with a pattern
line5
line6
line7 with a pattern

相关内容