Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/unix/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
grep由两个关键行分隔的文本块_Grep_Match_Textblock - Fatal编程技术网

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