0

I have an xml file which looks like below

INPUT XML FILE

<ReconSummary>
<entryName>Total Deep</entryName>
<Code>777</Code>
<License>L</License>
<Tran>H20</Tran>
<job>1234</job>
</ReconSummary>

<ReconSummary> <entryName>Total Saurav</entryName> <Code>666</Code> <License>L</License> <Tran>H20</Tran> <job>1234</job> </ReconSummary>

<ReconSummary> <entryName>Total Ankur</entryName> <Code>555</Code> <License>L</License> <Tran>H20</Tran> <job>1234</job> </ReconSummary>

I was trying to search the pattern "Total Deep" and after that i want to comment out the the tag after 3rd or 4th line of the matching pattern in xml file

My code is below

while read -r line do;
LineNum=`grep -n "Total Deep" input.xml | cut -d: -f 1`
TOTAL=`expr $LineNum + 4`
echo $LineNum
echo $TOTAL
done < file.txt

While executing the code i am getting below exception

expr: syntax error

Can anyone tell me what is wrong in this code?

Kusalananda
  • 333,661
  • Could you please check what the output of grep -n "Deep" Formula.xml | cut -d: -f 1 is? In general, it would be better to parse the XML file using an XML parser, such as xmlstarlet (but I'm a bit confused about what you're wanting XML line numbers for, as the XML format is not line oriented). – Kusalananda Mar 10 '21 at 11:44
  • The output is the line numbers where Deep is present like for eg 39806 and 45608 and i need to use it via shell scripting – DEEP MUKHERJEE Mar 10 '21 at 11:46
  • So, you get multiple values back? Do you recognize that using multiple values in expr at the same time would be a problem? What you have is something like expr 39806 45608 + 9. It would be better to tell us what the XML file is and what values needs to be extracted from it to achieve what you want to do. Using grep is not the right approach to reading an XML file. – Kusalananda Mar 10 '21 at 11:48
  • i have modified my questions and the xml file details has been added in my question. Could you please help me on this? – DEEP MUKHERJEE Mar 10 '21 at 11:57
  • Which line do you want to comment out? You say 3rd or 4th. Do you mean the <job> tag? – Kusalananda Mar 10 '21 at 12:02
  • The 4 line or the 3rd line i want to comment out like the 4th line after the matching pattern is 1234 or the 3rd line after the matching pattern is H20 – DEEP MUKHERJEE Mar 10 '21 at 12:04
  • Sorry, which line do you want to delete? Both the <job> and the <Tran> lines? I don't understand it when you say "or". – Kusalananda Mar 10 '21 at 12:05
  • Like for example i want to comment out the 4th line but not delete 1234 so that the output becomes Total Deep 777 L H20

    . This is just an example of the 4th line. The file contains other values in the 4th line as well. So i specifically wnt to comment the f4th line after the matching pattern

    – DEEP MUKHERJEE Mar 10 '21 at 12:08

1 Answers1

1

Your issue is that grep returns multiple line matching your expression. What you end up executing with expr is something like expr 1 3 4 + 4 (if there are matches on lines 1, 3, and 4). This is where your syntax error comes from.


From comments, it is clear that you want to comment out a particular child node from a particular ReconSummary node. If you had wanted to delete e.g. the job node, I would have suggested using

xmlstarlet ed -d '//ReconSummary[entryName = "Total Deep"]/job' file.xml >newfile.xml

... but commenting out rather than deleting is a bit more tricky.

Similar to an answer to your previous question that I wrote just moments ago, this would be done with an XSL transformation:

<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

<xsl:template match="/|node()|@"> <xsl:copy> <xsl:apply-templates select="node()|@"/> </xsl:copy> </xsl:template>

<xsl:template match="//ReconSummary[entryName = 'Total Deep']/job"> <xsl:text disable-output-escaping="yes">&lt;!-- </xsl:text> <xsl:copy-of select="."/> <xsl:text disable-output-escaping="yes"> --&gt;</xsl:text> </xsl:template>

</xsl:transform>

The XPATH query //ReconSummary[entryName = 'Total Deep']/job matches the job child node of the ReconSummary node whose entryName child node has the value Total Deep.

You can change this easily to instead comment out the Tran node. The XPATH query for that would be

//ReconSummary[entryName = 'Total Deep']/Tran`

To match both the job and the Tran node, use

//ReconSummary[entryName = 'Total Deep']/*[name()='job' or name()='Tran']

As in my previous answer, you would apply this XSL transformation to your XML file using either of

xmlstarlet tr transform.xsl file.xml >newfile.xml

or

xsltproc transform.xsl file.xml >newfile.xml

where you file is file.xml and the transformation is stored in transform.xsl.

Kusalananda
  • 333,661