Sign up ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. It's 100% free, no registration required.

I am trying to add field at the end of tag using sed script. Suppose I have a tag in XML file:

<book name="Sed tutorial" price="250"/>

Now I want to add field as Book_Width="A" after end of <book/> tag so that my tag becomes:

<book name="Sed tutorial" price="250" Book_Width="A"/>

I tried with sed:

sed '/<book "[^>]*>/ a Book_Width="A"'

but it gives:

<book name="Sed tutorial" price="250"/>
Book_Width="A"
share|improve this question
    
Related :) – Kroltan Aug 12 '15 at 14:43
up vote 10 down vote accepted

You should not parse xml with sed, use an xml parser like xmlstarlet instead. For your task it would be:

xmlstarlet ed -O --inplace --insert "/book" --type attr -n Book_Width -v A xml_file

The file content is then:

<book name="Sed tutorial" price="250" Book_Width="A"/>
  • The ed means edit mode to edit the xml tree
  • -O omits the xml tag
  • We want to insert something with --insert
  • "/book" is the path where to insert
  • --type attr: it's an attribute, we want to insert
  • The name -n of the attribute
  • The value -v
share|improve this answer
    
can I update xml_file rather printing its output – krishna Aug 12 '15 at 10:43
    
@krishna Yes with --inplace I added it to my answer – chaos Aug 12 '15 at 10:48
    
If Book_Width="A" already present in XML file then how can we skip that tag – krishna Aug 13 '15 at 10:30

in sed "a" appends a pattern IN A NEW LINE.

what you want to do is replace (substitute). Let's use a colon as separator for clarity:

sed 's:\(<book.*\)\(/>\):\1 Book_Width="A"\2:'

anything in \( .. \) is a pattern memorized by the order of appearance and recalled by \indexnumber , e.g. \1 will reproduce the first pattern saved.

So we are memorizing <book name="Sed tutorial" price="250" as pattern 1 and /> as pattern 2 and just insert Book_Width="A" in the middle.

echo '<book name="Sed tutorial" price="250"/>' | sed 's:\(<book.*\)\(/>\):\1 Book_Width="A"\2:'
<book name="Sed tutorial" price="250" Book_Width="A"/>
share|improve this answer

With awk you can do something like this:

Supposing the line is in file file1.xml then:

awk -F '/' '{print $1,"Book_Width=\"A\"",FS,$2}' file1.xml
share|improve this answer
    
This is not checking that the tag is "book" – glenn jackman Aug 12 '15 at 13:30

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.