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

Fah*_*tha 7 grep text-processing

考虑以下玩具示例:

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!
Run Code Online (Sandbox Code Playgroud)

所以,我想要 FOO 的 grep 的结果,但有额外的皱纹,应该包括匹配行之后的行,只要它们不是空白,并且它们本身不包含 FOO。因此匹配将如下所示,不同的匹配分开:

匹配 1

this line contains FOO 
this line is not blank
Run Code Online (Sandbox Code Playgroud)

第 2 场

This line also contains FOO
Run Code Online (Sandbox Code Playgroud)

第 3 场

This line contains FOO too 
Not blank 
Also not blank
Run Code Online (Sandbox Code Playgroud)

第 4 场

FOO!
Yet more random text
Run Code Online (Sandbox Code Playgroud)

第 5 场

FOO!
Run Code Online (Sandbox Code Playgroud)

可以在命令行上运行的简单单行脚本的加分点(比喻地说)。

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

Kus*_*nda 9

使用awk而不是grep

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

枚举匹配项的版本:

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
Run Code Online (Sandbox Code Playgroud)

这两个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!
Run Code Online (Sandbox Code Playgroud)


Mic*_*mer 6

sed -ne '/FOO/{x;P;x};/FOO/,/^$/p' testfile
Run Code Online (Sandbox Code Playgroud)

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

这个

  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!
Run Code Online (Sandbox Code Playgroud)


Ste*_*itt 5

我不认为这是可行的grep,但它适用于 AWK:

#! /usr/bin/awk -f

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

/^$/ {
  matched = 0
}

matched
Run Code Online (Sandbox Code Playgroud)

随着比赛的数量:

#! /usr/bin/awk -f

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

/^$/ {
  matched = 0
}

matched
Run Code Online (Sandbox Code Playgroud)

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