22

I am trying to convert

<id>1</id>
<Name>ENTERPRISE RESOURCE PLANNING</Name>

to:

<column name="id">1</column>
<column name="Name">ENTERPRISE RESOURCE PLANNING</column>

I am assuming the best tool for the job would be sed, however I can't figure out how to keep parts of the original text in the replace part.

If I do:

$ sed -i 's/<.*>.*<.*>/<column name="\\1">\\2<\/column>/g' filename.xml

The output is:

<column name="\1">\2</column>
<column name="\1">\2</column>

Or doing similar from within vi, it outputs:

<column name=""></column>
<column name=""></column>

How can I make it so that \1 and \2 are substituted back to their original values?

2 Answers 2

24

You can use groups, e.g.:

$ sed -i 's/<\(.*\)>\(.*\)<.*>/<column name="\1">\2<\/column>/g' filename.xml

Probably the most confusing part about REs is that there are various syntactic flavors.

For example sed and vim use basic regular expressions where you have to quote () to get their meta-meaning.

With extended regular expressions (e.g. awk, egrep and less) you have to quote () to get the literal meaning. There are similar differences for other meta-characters.

The rationale behind BRE () semantics is that when most of your input is C-Code then it is more practical to have to quote parentheses for meta-use.

2
  • This was actually the first thing I tried, but I didn't escape the ( and ) characters. Stupid question, but why is that necessary?
    – Mike
    Commented Sep 14, 2011 at 19:12
  • 1
    @Mike, good question - updated the answer. Commented Sep 14, 2011 at 19:30
1

Using xmlstarlet:

  1. Add an name attribute to all id and Name nodes, with the value id or Name as appropriate.
  2. Rename all name and id nodes to column.
xmlstarlet ed \
    -s '//id'   -t attr -n name -v id \
    -s '//Name' -t attr -n name -v Name \
    -r '//id'   -v column \
    -r '//Name' -v column  file.xml

Given an example document like

<root>
<id>1</id><Name>ENTERPRISE RESOURCE PLANNING</Name>
<id>2</id><Name>ENTERPRISE RESOURCE PLANNING (the return)</Name>
</root>

(note that white-spaces between nodes are not important) this would result in

<?xml version="1.0"?>
<root>
  <column name="id">1</column>
  <column name="Name">ENTERPRISE RESOURCE PLANNING</column>
  <column name="id">2</column>
  <column name="Name">ENTERPRISE RESOURCE PLANNING (the return)</column>
</root>

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .