我需要 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 第一a
行xyz
并打印所有行。
输出(第一个出现的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
这是如何运作的
它逐行读取文件并执行以下三件事之一:
- 如果当前行与模式匹配
a
,则将当前行分配给数组@buffer
。 - 如果当前行与模式匹配
xyz
,则将当前行推送到缓冲区并打印缓冲区的内容 - 如果上述两种情况都不成立,则它只是将当前行追加到
@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