grep由两个关键行分隔的文本块
我有一个文本文件,其中包含大致如下格式的文本块:grep由两个关键行分隔的文本块,grep,match,textblock,Grep,Match,Textblock,我有一个文本文件,其中包含大致如下格式的文本块: Beginning of block ... ... ... .........some_pattern....... ... ... End of block Beginning of block ... ... etc. 块可以有任意数量的行,但始终以两个分隔符开头。我想做的是匹配“某些模式”,并将整个块打印到标准输出。在上面的例子中,我只会得到以下结果: Beginning of block ... ... ... .........s
Beginning of block
...
...
...
.........some_pattern.......
...
...
End of block
Beginning of block
...
... etc.
块可以有任意数量的行,但始终以两个分隔符开头。我想做的是匹配“某些模式”,并将整个块打印到标准输出。在上面的例子中,我只会得到以下结果:
Beginning of block
...
...
...
.........some_pattern.......
...
...
End of block
我尝试过这样的方法,但没有成功:
grep "Beginning of block\n.*some_pattern.*\n.*End of block"
你知道怎么和grep一起做吗?(或者使用其他工具)我想awk更适合:
awk '/Beginning of block/ {p=1};
{if (p==1) {a[NR]=$0}};
/some_pattern/ {f=1};
/End of block/ {p=0; if (f==1) {for (i in a) print a[i]};f=0; delete a}' file
解释
当p
标志为“活动”且某些模式匹配时,它仅打印:
- 当它找到块的
开头时,则生成变量p=1
,并开始将行存储在数组a[]
中
- 如果它找到某个模式,它会将标志
f
设置为1,这样我们就知道该模式已经找到
- 当它找到
块的末尾时
将重置p=0
。如果自块的最后一个开始
以来发现了某些_模式
,则打印已存储的所有行。最后a[]被清除,f被重置;当我们再次遇到块的开始时,我们将有一个新的开始
其他测试
以下内容可能适用于您:
sed -n '/Beginning of block/!b;:a;/End of block/!{$!{N;ba}};{/some_pattern/p}' filename
sed对于这种治疗是有效的
使用grep,您当然应该通过中间文件或数组。这里有一种使用awk
的方法:
awk '/Beginning of block/ { r=""; f=1 } f { r = (r ? r ORS : "") $0 } /End of block/ { if (f && r ~ /some_pattern/) print r; f=0 }' file
结果:
Beginning of block
...
...
...
.........some_pattern.......
...
...
End of block
不确定我是否遗漏了什么,但下面是上述答案之一的一个简单变体:
awk'/块的开头/{p=1};
/块结尾/{p=0;打印$0};
{如果(p==1)打印$0}'
您需要在块的末尾
案例中打印输入行,以获得两个分隔符
我想要一个不打印分隔符的微小变化。在OP的问题中,分隔符模式简单且唯一。然后最简单的方法是将管道插入| grep-v块
。我的病例更不规则,所以我使用了下面的变异。请注意next
语句,以便第三条语句不会打印开头块:
awk'/块的开头/{p=1;next};
/块的结尾/{p=0};
{如果(p==1)打印$0}'
谢谢,但是我如何才能只检索包含“some\u pattern”的块呢?我已经更新了我的问题,以显示我正在寻找的输出。知道吗?嗯,那更复杂。在这种情况下,您可以将行保存在一个数组中,然后为“some_pattern”设置一个标志,最后打印它(如果存在)。我会在一段时间内试一试。@Laurent刚刚更新了此要求的正确解决方案。@Dining Spropher非常感谢您的支持!修正错误和改进解释:)这正是我想要的。谢谢
awk '/Beginning of block/ { r=""; f=1 } f { r = (r ? r ORS : "") $0 } /End of block/ { if (f && r ~ /some_pattern/) print r; f=0 }' file
Beginning of block
...
...
...
.........some_pattern.......
...
...
End of block