考虑以下玩具示例:
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
输出中的每个非空行块都是来自输入的匹配数据的单个块。换行符的数量各不相同。
这
- 抑制输出 (
-n
);然后 - 在每次出现“FOO”之前打印一个空行(
/FOO/{x;P;x}
- 使用空的保留空间); - 选择从包含 FOO ( ) 的行开始到空行 ( )
/FOO/
结束的行范围;/^$/
最后 - 打印这些行 (
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
省略默认打印中的终止空行作为练习留给读者;-)