0

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">
fedorqui
  • 275,237
  • 103
  • 548
  • 598
logan
  • 7,946
  • 36
  • 114
  • 185
  • 1
    You seem to be looking for a XML parser. See `xmllint`. – devnull Feb 07 '14 at 13:56
  • @devnull : No, it can any file.. this scenario is for xml file.. I have other files as well.. – logan Feb 07 '14 at 13:56
  • possible duplicate of [grep show 5 lines above grepped line](http://stackoverflow.com/questions/6281343/grep-show-5-lines-above-grepped-line) – devnull Feb 07 '14 at 13:58
  • @devnull : This is not duplicate.. This is not working, if the same actflg="1" repeats multiple time – logan Feb 07 '14 at 14:02

1 Answers1

3

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.
fedorqui
  • 275,237
  • 103
  • 548
  • 598
  • This is not showing , if the same actflg="1" repeats multiple time – logan Feb 07 '14 at 14:00
  • Well I replied based on your sample input. If you change the sample, don't come and downvote... – fedorqui Feb 07 '14 at 14:21
  • I did not do that !! Please remember that i am here to ask for help ! anyone's answer is well appreciated even if it is wrong because they help me !! – logan Feb 07 '14 at 14:28
  • OK I thought it was your downvote. It is a bit tricky because the way to do it will be `awk` but having the "ignore case" comparison it is more difficult. Will try to find a moment to figure out how to do it. – fedorqui Feb 07 '14 at 14:30
  • Thanks.. even if it is case sensitive its okay.. because its predefined structure file – logan Feb 07 '14 at 14:33
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/47032/discussion-between-logan-and-fedorqui) – logan Feb 07 '14 at 14:46
  • @logan updated with some information, hope it is clear. – fedorqui Feb 07 '14 at 15:00
  • error when using `-B` it in Solaris machine : `grep: illegal option -- B grep: illegal option -- 2 Usage: grep -hblcnsviw pattern file . . .` – logan Mar 03 '14 at 14:23
  • it have raised it here.. http://stackoverflow.com/questions/22149908/awk-command-to-print-last-5-rows-if-matched – logan Mar 03 '14 at 14:55