I am trying to replicate a workplace problem. I have a xml file like below[~]$ less -N sample.xml  1     <SOURCE BUSINESSNAME = NAME =TABLE1 FOO=ABCD..... >  2         <SOURCEFIELD BUSINESSNAME = NAME =COL_XYZ />  3         <SOURCEFIELD BUSINESSNAME = NAME =COL_ABCD />  4         ...  5                 ...  6     </SOURCE>  7     <SOURCE BUSINESSNAME = NAME =TABLE2 ....... >  8             <SOURCEFIELD BUSINESSNAME = NAME =COL_ABCD />  9         <SOURCEFIELD BUSINESSNAME = NAME =COL_XYZABC />     10         ... 11                 ... 12     </SOURCE> 13         <SOURCE BUSINESSNAME = NAME =TABLE3 .... > 14         <SOURCEFIELD BUSINESSNAME = NAME =COL_PQR /> 15         <SOURCEFIELD BUSINESSNAME = NAME =COL_ABCD /> 16         ... 17                 ... 18     </SOURCE>Now I want the value of NAME field where any of the SOURCEFIELD NAME is like XYZ. For example, in the given example I need TABLE1 as line 2 contains COL_XYZ. And also TABLE2 as in line 9 we have COL_XYZABCI was thinking some way, to get row 1,2,7,9,13 as output and then grep -B1 XYZ|grep -w SOURCE field to get only row 1,7 in output.Expected Output:TABLE1TABLE2What I tried so far Doing a grep on SOURCE is not working as every row has at least one of them.Doing a egrep -w SOURCE|XYZ is not working as I need XYZABC will not satisfy its condition.Could someone please suggest something which I can try to get desired result. I am using Linux 2.6.18-371.el5
How to extract particular field from rows from a file, based on matching subsequent rows
linux;grep;regular expression
You can accomplish this using the hold space feature of sed.Run sed with the -n option to suppress the automatic printing of input lines.When the line containing <SOURCE is seen, save the value of the NAME attribute in sed's hold space.When the <SOURCEFIELD line containing XYZ is seen, print the contents of the hold space.#!/bin/shsed -n '    /<SOURCE / {              # execute block {} on lines matching <SOURCE         s/.* NAME *=//       # remove everything upto NAME attribute value        s/.*//               # remove everything after attribute value        h                     # copy pattern space to the hold space    }    /<SOURCEFIELD.*XYZ/ {     # SOURCEFIELD contains XYZ, execute {} block        g                     # copy hold space to pattern space        p                     # print    }' $@