我有一个文本文件,其中包含大致格式如下的文本块:
Beginning of block
...
...
...
.........some_pattern.......
...
...
End of block
Beginning of block
...
... etc.
块可以有任意数量的行,但始终以两个分隔符开头。我想做的是匹配“some_pattern”并将整个块打印到stdout。通过上面的例子,我只会得到这个:
Beginning of block
...
...
...
.........some_pattern.......
...
...
End of block
我尝试过这样的事情却没有成功:
grep "Beginning of block\n.*some_pattern.*\n.*End of block"
知道怎么用grep做这个吗? (或者可能使用其他工具)
答案 0 :(得分:9)
我猜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
标志为“有效”并且some_pattern
匹配时打印:
Beginning of block
后,生成变量p=1
并开始在数组a[]
中存储这些行。some_pattern
,则会将标记f
设置为1,以便我们知道已找到该模式。End of block
后,它会重置p=0
。如果自上次some_pattern
后找到Beginning of block
,则会打印已存储的所有行。最后清除[]并重置f;当我们再次遇到Beginning of block
时,我们将有一个新的开始。$ cat a
Beginning of block
blabla
.........some_pattern.......
and here i am
hello
End of block
Beginning of block
...
... etc.
End of block
$ 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]}; delete a;f=0}' a
Beginning of block
blabla
.........some_pattern.......
and here i am
hello
End of block
答案 1 :(得分:4)
以下内容可能适合您:
sed -n '/Beginning of block/!b;:a;/End of block/!{$!{N;ba}};{/some_pattern/p}' filename
答案 2 :(得分:1)
这是使用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
答案 3 :(得分:0)
sed -n "
/Beginning of block/,/End of block/ {
N
/End of block/ {
s/some_pattern/&/p
}
}"
sed对于这种治疗是有效的
使用grep,你当然应该通过中间文件或数组。
答案 4 :(得分:0)
不知道我是否错过了什么,但这是上述答案之一的更简单的变化:
awk '/Beginning of block/ {p=1};
/End of block/ {p=0; print $0};
{if (p==1) print $0}'
您需要在End of Block
情况下打印输入行才能获得两个定界符。
我想要一个不打印定界符的细微变化。在OP的问题中,定界符模式是简单且唯一的。然后最简单的方法是将其插入| grep -v block
。我的情况更加不规则,因此我使用了以下变体。请注意next
语句,因此第三个语句不会打印出开始符:
awk '/Beginning of block/ {p=1; next};
/End of block/ {p=0};
{if (p==1) print $0}'```