【问题标题】:grep - print line before, don't print matchgrep - 打印前行,不打印匹配
【发布时间】:2013-07-30 09:51:24
【问题描述】:

如何轻松打印匹配上方的行并跳过匹配本身? grep-A-B-o opt 不解决。也许是一些awk 魔法?

例如:

$ cat foo.txt
bar
foo
baz
foo

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

编辑

  • 如果第 2 行和第 3 行有“foo”,则应该打印第 1 行和第 2 行(虽然我这里不是很严格)

附加功能:考虑示例:

bar
foo
baz
foo
foo

理想情况下应该返回

bar
baz
foo

【问题讨论】:

  • -B 有什么问题?
  • @AdrianFrühwirth 它打印前一行和匹配行。
  • 两条连续线都匹配 foo 怎么样?打印第一行?还是两者都忽略?
  • @Barmar:我知道这一点,但这可以解决。

标签: awk grep


【解决方案1】:
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
  • awk '/foo/{ print line } { line = $0 }' foo.txt 不应该足够吗?
  • @AdrianFrühwirth:请将其作为答案发布,它在处理重复匹配模式时表现更好(请参阅已编辑的问题)
  • @JakubM。这是我的回答,也是维杰的回答。
  • @Barmar:我以为阿德里安在你之前,如果我错了,对不起
【解决方案2】:

只需将p 设置为您想要的模式:

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

【讨论】:

    【解决方案3】:
    awk '/foo/{print a}{a=$0}' your_file
    

    【讨论】:

      最近更新 更多