Grepping 字符串,但包含每个 grep 匹配后面的所有非空行

Grepping 字符串,但包含每个 grep 匹配后面的所有非空行

考虑以下玩具示例:

this is a line 
this line contains FOO 
this line is not blank

This line also contains FOO

Some random text

This line contains FOO too
Not blank 
Also not blank

More random text 
FOO!
Yet more random text
FOO!

因此,我想要 FOO 的 grep 结果,但有一点额外的问题,即应该包括匹配行后面的行,只要它们不为空,并且它们本身不包含 FOO。因此,匹配项将如下所示,不同的匹配项分开:

比赛1

this line contains FOO 
this line is not blank

比赛2

This line also contains FOO

比赛3

This line contains FOO too 
Not blank 
Also not blank

第4场比赛

FOO!
Yet more random text

比赛5

FOO!

可以在命令行上运行的简单单行脚本的奖励点(比喻而言)。

附录:如果不是太难的话,添加比赛号码的运行计数会非常方便。

答案1

使用awk而不是grep

awk '/FOO/ { if (matching) printf("\n"); matching = 1 }
     /^$/  { if (matching) printf("\n"); matching = 0 }
     matching' file

枚举匹配的版本:

awk 'function flush_print_maybe() {
         if (matching) printf("Match %d\n%s\n\n", ++n, buf)
         buf = ""
     }
     /FOO/ { flush_print_maybe(); matching = 1 }
     /^$/  { flush_print_maybe(); matching = 0 }
     matching { buf = (buf == "" ? $0 : buf ORS $0) }
     END   { flush_print_maybe() }' file

这两个awk程序都使用一个非常简单的“状态机”来确定当前是否匹配。模式的匹配FOO将使其进入matching状态,模式的匹配^$(空行)将使其进入非状态matching

匹配数据集之间的空行输出发生在状态转换时 matching(进入matching或进入非matching)。

第一个程序在处于该matching状态时打印任何行。

第二个程序buf在某种状态下收集变量中的行matching。它在可能打印它(取决于状态)之后刷新(清空)它,以及Match N状态转换时的标签(当第一个程序输出空行时)。

最后一个程序对样本数据的输出:

Match 1
this line contains FOO
this line is not blank

Match 2
This line also contains FOO

Match 3
This line contains FOO too
Not blank
Also not blank

Match 4
FOO!
Yet more random text

Match 5
FOO!

答案2

sed -ne '/FOO/{x;P;x};/FOO/,/^$/p' testfile

输出中的每个非空行块都是来自输入的匹配数据的单个块。换行符的数量各不相同。

  1. 抑制输出 ( -n);然后
  2. 在每次出现“FOO”之前打印一个空行(/FOO/{x;P;x}- 使用空的保留空间);
  3. 选择从包含 FOO ( ) 的行开始到空行 ( )/FOO/结束的行范围;/^$/最后
  4. 打印这些行 ( p)。

this line contains FOO
this line is not blank


This line also contains FOO


This line contains FOO too
Not blank
Also not blank


FOO!
Yet more random text

FOO!

答案3

我不认为这对于 是可行的grep,但对于 AWK 是可行的:

#! /usr/bin/awk -f

/FOO/ {
  matched = 1
  if (notfirst) print ""
  notfirst = 1
}

/^$/ {
  matched = 0
}

matched

匹配次数:

#! /usr/bin/awk -f

/FOO/ {
  matched = 1
  if (matches) print ""
  printf "Match %d\n", ++matches
}

/^$/ {
  matched = 0
}

matched

在这两种情况下,前两个块确定是否应将当前记录复制到输出。当当前记录匹配“FOO”时,第一个块设置matched为1,如果需要则输出空白记录(以将即将输出的内容与上一个匹配的内容分开);在第二种变体中,它还增加matches计数器并输出标头。当当前记录为空时,第二个块设置为 0。如果为 1,matched孤独matched条件将打印当前记录。matched

答案4

awk '/FOO/{print "===match " ++i "==="} /FOO/,/^$/' file

===match 1===
this line contains FOO
this line is not blank

===match 2===
This line also contains FOO

===match 3===
This line contains FOO too
Not blank
Also not blank

===match 4===
FOO!
Yet more random text
===match 5===
FOO!

类似的变体FOO可以轻松更改为其他内容:

awk -vpat=FOO '$0~pat{print "===match " ++i "==="} $0~pat,/^$/' file

省略默认打印中的终止空行作为练习留给读者;-)

相关内容