grep - 打印匹配行之前的行,不打印匹配行

14

如何轻松打印匹配行之前的行并跳过匹配行本身?grep命令中的-A-B-o选项均无法解决此问题。也许需要一些awk魔术?

例如:

$ cat foo.txt
bar
foo
baz
foo

$ cat foo.txt | grep foo-SOMETHING
bar
baz

编辑

  • 如果第二和第三行都包含“foo”,则应打印第一和第二行(尽管我在这里不是非常严格)。

附加功能:考虑以下示例:

bar
foo
baz
foo
foo

理想情况下应该返回

bar
baz
foo

1
“-B”有什么问题吗? - Adrian Frühwirth
3
它会打印出前一行和匹配到的那一行。 - Barmar
两行连续的文本都匹配“foo”怎么办?打印第一行还是忽略两行? - Kent
@Barmar:我知道这一点,但可以通过解决来规避这个问题。 - Adrian Frühwirth
3个回答

20
awk '!/foo/ { line = $0 }
     /foo/ { print line }' foo.txt

第一条子句将每个非“foo”行保存在一个变量中。第二条子句在该行匹配foo时打印最近保存的行。

这种方法也适用于处理连续两个foo行的情况:

awk '/foo/ {print line}
     {line = $0}' foo.txt

使用 grep 你可以做到:

grep -B 1 foo foo.txt | grep -vE 'foo|^--$'

第二个命令过滤掉匹配块之间打印的 foo 行和分隔符。


如果在匹配到 foo 的行后面应该打印包含 foo 的行,则重构为 awk '/foo/{print line}{line=$0}' foo.txt - tripleee
1
awk '/foo/{ print line } { line = $0 }' foo.txt 不应该足够吗? - Adrian Frühwirth
@AdrianFrühwirth:请将其发布为答案,在处理重复匹配模式时更加有效(请参见编辑后的问题)。 - Jakub M.
@JakubM。这在我的答案中,也在Vijay的答案中。 - Barmar
@Barmar:我以为Adrian比你先回复了,如果我错了请原谅。 - Jakub M.
@JakubM。他提出了建议后,我更新了我的回答。 - Barmar

3

只需将p设置为所需的模式即可:

$ awk '$0~p{print a}{a=$0}' p="foo" file
bar
baz
foo

2
awk '/foo/{print a}{a=$0}' your_file

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接