如何在文件及其上方和下方的行中排除匹配的模式?

时间:2018-12-19 17:14:28

标签: linux sed grep

除了三行之一包含Result: False之外,我要打印包含service.dead及其上方三行的行。

对于以下文件:

      ID: service1
Function: module.run
    Name: ps.kill_pid
  Result: True
 Comment: State was not run because onfail req did not change
 Started: 16:37:23.237741
Duration: 0.0 ms

      ID: service2
Function: service.dead
    Name: SomeService
  Result: False
 Comment: check_cmd determined the state failed
 Started: 16:37:23.567741
Duration: 8286.0 ms

      ID: service3
Function: service.running
    Name: SomeService
  Result: True
 Comment: Started Service SomeService
          Delayed return for 5 seconds
 Started: 16:38:22.956741
Duration: 47438.0 ms

      ID: check_status
Function: cmd.run
    Name: http.query http://1.1.1.1 
  Result: False
 Comment: Attempt 1: Returned a result of "False"
          Attempt 2: Returned a result of "False"
          Command "http.query http://1.1.1.1"
 Started: 16:40:57.424741
Duration: 50180.0 ms

我只想打印

ID: check_status
Function: cmd.run
    Name: http.query http://1.1.1.1 
  Result: False

我设法使用以下命令在Result: False上方打印了三行,并在service.dead下方删除了两行:

grep -B 3 'Result: False' /my/file | sed '/service.dead/,+2d'

但是我找不到如何删除service.dead上方的行。我当前的输出是:

      ID: Service2
---
      ID: check_status
Function: cmd.run
    Name: http.query http://1.1.1.1 
  Result: False

有什么优雅的方法吗?

2 个答案:

答案 0 :(得分:1)

您可以使用awk:

awk '
    BEGIN {
        RS = ""
        FS = OFS = "\n"
    }
    $4 ~ /Result: False/ && !($2 ~ /service\.dead/) {
        print $1, $2, $3, $4
    }
' infile

这将执行以下操作:

  • 将记录分隔符RS设置为空字符串,这告诉awk记录由空行分隔
  • 各字段之间用换行符分隔,以用于输入(FS)和输出(OFS
  • 对于每条记录,我们将字段4和2与所需值进行比较,如果匹配成功,则打印前四个字段

答案 1 :(得分:0)

这可能对您有用(GNU sed):

sed -n ':a;N;s/\n/&/3;Ta;/service\.dead/ID;/Result:\s*False[^\n]*$/Ip;D' file

使用-n选项关闭自动打印。在文件的整个长度中打开一个四行窗口。如果模式空间中保存的四行中的任何一行包含文本service.dead,请删除第一行并追加另一行。如果模式空间中四行的最后一行以Result: False结尾,则打印模式空间。无论先前的结果如何,都删除第一个结果,然后追加下一个结果,并保留四行窗口。