grep(awk)从A到第一个空行的文件

时间:2014-05-23 14:24:34

标签: bash awk grep

我需要将包含Pattern A的行中的文件grep到第一个空行。 我使用awk,但我不知道如何编码这个空行。

cat ${file} | awk '/Pattern A/,/Pattern B/'

4 个答案:

答案 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