grep或sed使用相同的模式匹配开始和结束之间的块

时间:2017-08-15 07:59:08

标签: perl unix awk sed grep

我有一个包含以下信息的文件:

start pattern1
line1
line2
...
end pattern1
line3
line4
start pattern2
...

我的输出应该是:
start pattern1 line1 line2 end pattern1

如果我知道pattern1是什么,我可以做

sed '/start pattern1/,/end pattern1/p' <file>

但是在这里,我希望匹配pattern1(如perl正则表达式中的\S+)并最终使用相同的内容(如$1)。我怎么能这样做?

5 个答案:

答案 0 :(得分:4)

使用Perl中的range operator,不会同时测试模式

do

更新为评论中指定的实际模式。

我使用捕获进行测试(在print块中而不仅仅是...)并且它有效,但问题可能在于等待是否有其他捕获。如果你不捕获任何其他正则表达式中的任何东西,这都有效。

请注意,使用..代替{{1}},测试正确的操作数,直到下次评估。

答案 1 :(得分:1)

使用awk在pattern1 s(包括)之间打印:

$ awk '/pattern1/{p=!p;print;next} p' file
pattern1
line1
line2
...
pattern1

可以更好地定义正则表达式,例如/^pattern1$/$0=="pattern1"

答案 2 :(得分:1)

这可能适合你(GNU sed):

sed -n '/pattern/,//p' file

这会调用一个触发器匹配的范围,空//匹配最后一个正则表达式。 p在范围切换为真时打印所有内容。

N.B。 -n调用类似于grep的性质并关闭自动打印。

替代方案:

sed '/pattern/!d;:a;n;//!ba' file

答案 3 :(得分:0)

尝试使用awk解决方案,并告诉我这是否对您有所帮助。

awk -v RS="" '{match($0,/start pattern1.*start pattern1/);print substr($0,RSTART,RLENGTH)}'  Input_file

编辑: OP没有显示像Input_file也可能有空行,根据CWLiu,我添加了一个建议,如果有任何空行也可以。

awk '/start pattern1/{print;getline;while($0 !~ /start pattern1/){print;getline};print}' Input_file

答案 4 :(得分:0)

所以,这里的awk实施基于对您问题的替代解释(因为它不太清楚)。

如果要检测以pattern1开头的第一行中的start,然后将每行打印到end pattern1,您可以这样做:

$ awk '/^start / {pat=$2; next}  /^end / && $2~pat {exit}  {print}' file 
line1
line2
...