Score:4

Using sed with a variable inside double quote

kr flag

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.

Score:5
cn flag

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

Score:2
tj flag

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

terdon avatar
cn flag
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`.
fuzzy drawings avatar
tj flag
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.
mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.