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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM