Unix Bash shell command to grep some text if anoth

2019-08-27 23:03发布

问题:

I have an XML file in unix directory. I would like to search for some character if that is present, then grep the text located 3 lines before this matched line,.

Here is My File: (abc.xml)

<task Col="5" Object="BCD">
<checkpoint TcpOn="0"/>
<after ActFlg="0"/>
</task>
<task Col="6" Object="ABCD">
<checkpoint TcpOn="0"/>
<after ActFlg="1"/>
</task>
<task Col="7" Object="ABCDE">
<checkpoint TcpOn="0"/>
<after ActFlg="1"/>
</task>

Unix Code:

grep -i 'actflg="1"' abc.xml

Current Answer: This is returning the line where it is located.

<after ActFlg="1"/>
<after ActFlg="1"/>

What i Want is : (i want to do a further grep to display output as follows if actflg="1" is found...)

<task Col="6" Object="ABCD">
<task Col="7" Object="ABCDE">

回答1:

You can use grep -B XX, which print XX lines before matching lines. Then you use head -1 to just print the first one:

$ grep -B2 -i 'actflg="1"' file
<task Col="6" Object="ABCD">
<checkpoint TcpOn="0"/>
<after ActFlg="1"/>

$ grep -B2 -i 'actflg="1"' file | head -1
<task Col="6" Object="ABCD">

In case there are multiple matches, you can do:

$ awk '/ActFlg="1"/ {print preprev} {preprev=prev; prev=$0}' file
<task Col="6" Object="ABCD">
<task Col="7" Object="ABCDE">

Explanation

  • '/ActFlg="1"/ {print preprev} matches lines containing ActFlg="1" and does print preprev, a stored line.
  • {preprev=prev; prev=$0} this keeps storing the two previous lines. The 2 before is stored in preprev and the previous in prev. So whenever we are in a new line, this gets updated.