awk匹配以aaa开头,以bbb结尾的内容,同时aaa和bbb之间还包含ccc
如果是匹配以A开头,以B结尾的内容,同时A和B之间还包含C的这种怎么做?
比如
[root@localhost ~]#cat file aaa grge ddd bbb aaa gege ccc bbb aaa gregeg eee bbb
这个中A=aaa,B=bbb,C=ccc,那么要提取出下面的……
aaa gege
ccc
bbb
[root@localhost ~]#awk '/aaa/{t=1}{if(t)s=length(s)?s"\n"$0:$0}/bbb/{t=0;if(s~/ccc/)print s;s=""}' file
第一行
pattern1{action1}
匹配包含aaa的行,满足条件令t=1,当t=1时,if条件为真,执行s=length(s)?s"\n"$0:$0
这里s=length(s)?s"\n"$0:$0先赋值再判断
length(s)为真,执行s"\n"$0;s=s"\n"$0,将$0添加到s的下一行
length(s)为假,执行$0
man awk中length函数的解释
length([s]) Return the length of the string s, or the length of $0 if s is not supplied.
length(s)=length($0),即length(aaa)=3,表达式为真,此时执行第1个表达式 s"\n"$0
[root@localhost ~]#echo "aaa" | awk '{s=length(s)?s"\n"$0:$0}END{print s}' aaa [root@localhost ~]#echo "aaa" | awk '{s=length(s)}END{print s}' 0
pattern2{action2}
匹配包含bbb的行
s为从aaa开始的字符串
判断字符串中是否包含ccc(正则表达式)
满足条件,则打印s
不满足将s变量置空
第二行
不匹配aaa,由于第一行不满足bbb,所以t=1;
执行{if(t)s=length(s)?s"\n"$0:$0}
s值累加,继续将$0添加到s的下一行
不匹配bbb,执行下一行
第三行
不匹配aaa,继续将$0添加到s的下一行
不匹配bbb,执行下一行
第四行
不匹配aaa,继续将$0添加到s的下一行
匹配bbb,执行{t=0;if(s~/ccc/)print s;s=""}
将t置0,执行正则匹配,s是否包含ccc
满足条件,打印s
不满足条件,将s置空
一个循环结束(或者一个流程结束,若不满足条件则无法完成,后面的代码也就失去意义了)
改进:
length函数可以不用
awk '/aaa/{t=1}{if(t)s=s?s"\n"$0:$0}/bbb/{t=0;if(s~/ccc/)print s;s=""}' file
多种思路,感谢CU大神
awk '/^aaa/{t=1};/^bbb/{if(s~/ccc/){print s"\n"$0};s=a;t=0}t{s=s?s"\n"$0:$0}' file
awk '/^aaa/{s=$0;next};/^bbb/{if(s~/ccc/)print s"\n"$0;next}{s=s"\n"$0}' file