如果是匹配以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