我需要将包含Pattern A
的行中的文件grep到第一个空行。
我使用awk
,但我不知道如何编码这个空行。
cat ${file} | awk '/Pattern A/,/Pattern B/'
答案 0 :(得分:7)
sed
可能是最好的:
sed -n '/PATTERN/,/^$/p' file
为避免打印空行:
sed -n '/PATTERN/,/^$/{/^$/d; p}' file
甚至更好 - thanks jthill!:
sed -n '/PATTERN/,/^$/{/./p}' file
如果PATTERN
出现多次,上述解决方案将提供比所需更多的输出。为此,最好在找到空行后退出,如jaypal's answer suggests:
sed -n '/PATTERN/,/^$/{/^$/q; p}' file
^$
匹配空行,因为^
代表行的开头,$
代表行尾。因此,^$
表示:行的开头和结尾之间不包含任何内容。/PATTERN/,/^$/{/^$/d; p}
/PATTERN/,/^$/
匹配从PATTERN
到空行的行。{/^$/d; p}
删除(d
)行^$
格式的行,打印(p
)其余行。{/./p}
只打印那些至少包含一个字符的行。使用awk
,您可以使用:
awk '!NF{f=0} /PATTERN/ {f=1} f' file
与sed
相同,如果它有多行PATTERN
则会失败。为此,让我们一旦找到空行就退出:
awk 'f && !NF{exit} /PATTERN/ {f=1} f' file
!NF{f=0}
如果没有字段(即行为空),请取消设置标记f
。/PATTERN/ {f=1}
如果找到PATTERN,请设置标记f
。f
如果设置了标记f
,则为True,因此它执行默认的awk行为:打印该行。$ cat a
aa
bb
hello
aaaaaa
bbb
ttt
$ awk '!NF{f=0} /hello/ {f=1} f' a
hello
aaaaaa
bbb
$ sed -n '/hello/,/^$/{/./p}' a
hello
aaaaaa
bbb
答案 1 :(得分:6)
使用sed
:
sed -n '/PATTERN/,/^$/{/^$/q;p;}' file
使用regex
范围,您可以定义从PATTERN
到空白行(/^$/
)的范围。当您遇到空行时,您退出,否则您继续打印。
使用awk
:
awk '/PATTERN/{p=1}/^$/&&p{exit}p' file
您在遇到PATTERN
时启用了一个标记。当您到达空白行并启用标记时,退出。如果没有,你继续打印。
评论中devnull建议的另一个替代方法是使用pcregrep
:
pcregrep -M 'PATTERN(.|\n)*?(?=\n\n)' file
答案 2 :(得分:3)
我认为这是一个很好的,可读的Perl单行代码:
perl -wne '$f=1 if /Pattern A/; exit if /^\s*$/; print if $f' file
$f
测试出来:
$ cat file
1
2
Pattern A
3
4
5
6
7
8
9
$ perl -wne '$f=1 if /Pattern A/; exit if /^$/; print if $f' file
Pattern A
3
4
5
6
或者,根据suggestion by @jaypal,您可以这样做:
perl -lne '/Pattern A/ .. 1 and !/^$/ ? print : exit' file
范围运算符$f
不是使用标记..
,而是为您处理此问题。当"模式A"时,它评估为真。在线上找到并且无限期保持真实。如果是,则将评估其他部分,并print
直到找到空行。
答案 3 :(得分:2)
永远不要使用
/foo/,/bar/
除非你想从第一次出现" foo"到最后一次出现" bar"因为它使琐碎的工作略微简短,但即使是稍微有趣的要求也需要完全重写。
只需使用:
/foo/{f=1} f{print; if (/bar/) f=0}
或类似的。
如果awk解决方案是:
awk '/pattern/{f=1} f{print; if (!NF) exit}' file