4

I have a file input.xml which contains a line: <exciton lambda="1" fix="hole"/>

in that line I want to replace 1 with 2 but I can't use just 1 as key word since there are other instances of "1" in the same file so I have to use the keyword lambda="1"

I am trying to use sed command as below:

sed -i "s/lambda="1"/lambda="$value"/g" input.xml

But it's not working, can anybody please help.

2 Answers 2

5

First of all, it is never a good idea to try to parse XML or other such structured text with regular expressions. While theoretically possible to do well and safely, it is extremely hard even for experts. Far better to use a dedicated tool that is designed to handle the language you have. So if this is an XML file, you could use something like xmlstarlet instead. For example, given this input file:

$ cat file.xml
<?xml version="1.0"?>
<record id="1">
  <exciton lambda="1" fix="hole"/>
</record>

You could do:

$ value="1234"
$ xml ed -u "//record[@id=1]/exciton/@lambda" -v "$value" file.xml 
<?xml version="1.0"?>
<record id="1">
  <exciton lambda="1234" fix="hole"/>
</record>

All that said, with the very minimal information you have given us, it is possible that you can do it using a simple, naive parser like sed. There are various tricks you can try. First, just escape the double quotes:

$ sed "s/lambda=\"1\"/lambda=\"$value\"/" file.xml
<?xml version="1.0"?>
<record id="1">
  <exciton lambda="1234" fix="hole"/>
</record>

Or, use single quotes but end them and insert the quoted variable outside the single quotes. Then, open a new single quotes sting to continue the sed expression:

$ sed 's/lambda="1"/lambda="'"$value"'"/' file.xml
<?xml version="1.0"?>
<record id="1">
  <exciton lambda="1234" fix="hole"/>
</record>

That one is a bit hard to parse visually, but this is what it is doing with added whitespace for legibility (note that it doesn't actually work with the added whitespace, this is only for clarity):

sed 's/lambda="1"/lambda="'   "$value"   '"/' file.xml

You have two options. First, you can simply escape the double

2

I am trying to use sed command as below :

sed -i "s/lambda="1"/lambda="$value"/g" input.xml

Assuming value is already defined, enclose the variable with single quotes: '$value':

sed -i 's/lambda="1"/lambda="'$value'"/g' input.xml

EDIT as @terdon pointed, if your value variable contains whitespace the above will not work and you will need to double-quote the variable within the single quotes:

sed -i 's/lambda="1"/lambda="'"$value"'"/g' input.xml

2
  • 2
    This will fail if $value contains whitespace. This is because you aren't actually enclosing $value in single quotes here. After all, variables enclosed in single quotes are not expanded. The quotes simply end the single-quoted sed expression and start a new one. To make this safe, you need: sed -i 's/lambda="1"/lambda="'"$value"'"/g' input.xml. Jan 30, 2022 at 13:05
  • OP indicated that value would be 2 (another integer), but yes it will fail if he instead used a value containing white space or line endings. I guess I need to get in the habit of always using double-quoted variables. Jan 31, 2022 at 0:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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