Question: I'm trying to update a line in an xml file using a custom shell function and sed

In cmd line, I run it as follow:
updateloc db\_name

However it does not update anything. Below sample of the code

```
updateloc(){
 db_name=$1
 file="file.xml"
 olddb="<dbname><![CDATA[olddb]]></dbname>"
 newddb="<dbname><![CDATA[$db_name]]></dbname>"
 sed -i '' 's/$olddb/$newdb/g' $file

```

}

Answer: 
The right tool for this job is XMLStarlet. To modify any element named `dbname` with the new value:

```
updateloc() {
  local db_name=$1 file=file.xml
  xmlstarlet ed --inplace -u '//dbname' -v "$db_name" "$file"
}

```

To replace only elements with the old value `olddb`:

```
updateloc() {
  local db_name=$1 file=file.xml
  xmlstarlet ed --inplace \
    -u "//dbname[. = 'olddb']" -v "$db_name" "$file"
}

```

Note that while the serialization generated by XMLStarlet won't necessarily use `CDATA`, it is guaranteed to be semantically equivalent, and to behave the precise same way in any XML-compliant parser.
1) $olddb and $newdb are not getting expanded because they're in single quotes

2) Your sed command is getting tripped up by all those xml characters - '[' and '/' are both meaningful to sed. You'd have to escape all those, and perhaps use a different regex delimiter (e.g. 's#$olddb#$newdb#g'). It's probably a bad idea to use sed for this, unless the format of file.xml is very consistent (the closing tag could be on a separate line for example).

That said, this would work for your example:

```
olddb='<dbname><!\[CDATA\[olddb\]\]></dbname>'
newdb='<dbname><!\[CDATA\[newdb\]\]></dbname>'
sed -i '' "s#$olddb#$newdb#g" $file

```

[Grep and Sed Equivalent for XML Command Line Processing](https://stackoverflow.com/questions/91791/grep-and-sed-equivalent-for-xml-command-line-processing) has some good approaches for better ways to mangle xml from the command line.