搜索一个模式并打印以另一个模式开头的前几行

搜索一个模式并打印以另一个模式开头的前几行

我需要 grep 查找一个模式,一旦找到它,我需要寻找该模式之前的另一个模式并打印它们之间的所有这些行。

更好的例子:

1 a
2 a
3 a
4 a
5 a
6 b
7 c
8 d
9 xyz
10 xyz
11 a
12 a

grep forxyz然后 grep for 第一axyz并打印所有行。

输出(第一个出现的a,我不关心a文件中的其他 ):

5 a 
6 b
7 c
8 d
9  xyz
10 xyz

答案1

这是 Perl 中的解决方案:

perl -nlE '
    if    (/a/)   { @buffer = ($_) }
    elsif (/xyz/) { push @buffer,$_; say for @buffer }
    else          { push @buffer,$_}
' your_file

这是如何运作的

它逐行读取文件并执行以下三件事之一:

  1. 如果当前行与模式匹配a,则将当前行分配给数组@buffer
  2. 如果当前行与模式匹配xyz,则将当前行推送到缓冲区并打印缓冲区的内容
  3. 如果上述两种情况都不成立,则它只是将当前行追加到@buffer数组中。

因此,每当新行与模式匹配时a, 的内容@buffer都会被删除并仅由当前行替换。这保证您会找到最接近的a前面的xyz.

当然,您应该将我使用的正则表达式替换为与您的案例相关的实际正则表达式。

答案2

思考你可以做类似的事情

grep -zPo '.*a(?s)(?(?!a).)*?xyz' file

(使用 GNU grep,如果您的版本足够新以支持 PCRE 扩展)或

pcregrep -Mo '.*a(?s)(?(?!a).)*?xyz' file

如果您想匹配xyz输出中的第二个实例,请通过删除最后的?eg使匹配变得贪婪grep -zPo '.*a(?s)(?(?!a).)*xyz' file


也许更好的测试是这样的,对于开始和停止条件都使用多字符模式;给定

$ cat file
1 abc    
2 abc
3 abc
4 abc
5 abc
6 bbc
7 cbc
8 dbc
9 xyz
10 xyz
11 abc
12 abc

然后

$ grep -zPo '.*abc(?s)(?(?!abc).)*?xyz' file
5 abc
6 bbc
7 cbc
8 dbc
9 xyz

答案3

tac file | sed '/xyz/,/a/!d' | tac

(如果您没有tac,您的tail命令可能有一个-r执行相同操作的命令)。

答案4

如果您不关心输出中的空行,请尝试:

$ awk '
    !NF { next }
    /a/ { flag = 1; last = $0; next }
    last && flag { print last; print; last = 0; next}
    /xyz/ { print; flag = 0; next}
    flag
' file
5 a
6 b
7 c
8 d
9 xyz
10 xyz

相关内容