I want create simple xml file using bash script ( not with dom )

but when I set value in the line then echo print the $lorem word and not the val


echo '<root><foo a="b">$lorem</foo><bar value="ipsum" /></root>' >> $MY_XML

I also try this

echo '<root><foo a="b">\$lorem</foo><bar value="ipsum" /></root>' >> $MY_XML

echo '<root><foo a="b">"$lorem"</foo><bar value="ipsum" /></root>' >> $MY_XML

echo '<root><foo a="b">\"$lorem\"</foo><bar value="ipsum" /></root>' >> $MY_XML

but all these print the exactly the line and not the val

please advice how to print the val $lorem ? as the following example

 <root><foo a="b">LOL</foo><bar value="ipsum" /></root>

4 Answers 4


Print the line on this way:

echo '<root><foo a="b">'"$lorem"'</foo><bar value="ipsum" /></root>' >> "$MY_XML"

This is need because single quotes deny shell interpreter from replace environment variables inside


Use in-line document with cat

cat >destfile <<EOF
<your ZML here...where $vas expand happly>
but the rest remain as is

I used it in a lot of scripts. Consider also envsubst command to restrict variables you can use in the in-line document.


Frustratingly perhaps, one of the combinations you omitted would have worked:

echo "<root><foo a=\"b\">$lorem</foo><bar value=\"ipsum\" /></root>" >> $MY_XML

Single quotes leave everything exactly as you type it. Escaping with \ will not work. Double quotes will evaluate the string. Inside double quotes you can use \ to escape specific characters (including the double-quote character itself).

You could also combine parts of the string that are quoted in different ways. Here, $lorem remains double-quoted but the rest of the string is surrounded with single quotes:

echo '<root><foo a="b">'"$lorem"'</foo><bar value="ipsum" /></root>' >> $MY_XML

The issue is that you are using your variable in a single-quoted string. The shell will never expand variables in single quoted strings.

Another issue is that the value in $lorem would not be properly XML encoded, so that a value like <!-- would mess up the XML document and make it unparseable.

Instead, use the jo from https://jpmens.net/2016/03/05/a-shell-command-to-create-json-jo/ to create a JSON document and the yq tool from https://kislyuk.github.io/yq/ to convert this to XML:

% lorem=LOL
% jo -p root="$( jo 'foo[@a]'=b 'foo[#text]'="$lorem" 'bar[@value]'=ipsum )"
   "root": {
      "foo": {
         "@a": "b",
         "#text": "LOL"
      "bar": {
         "@value": "ipsum"

Then pass this through yq -x to convert to XML. Keys starting with @ will be turned into node attributes, and the value of the #text key will be turned into the node's value.

% jo -p root="$( jo 'foo[@a]'=b 'foo[#text]'="$lorem" 'bar[@value]'=ipsum )" | yq -x
  <foo a="b">LOL</foo>
  <bar value="ipsum"></bar>

With the value <!-- in $lorem:

% lorem='<!--'
% jo -p root="$( jo 'foo[@a]'=b 'foo[#text]'="$lorem" 'bar[@value]'=ipsum )" | yq -x
  <foo a="b">&lt;!--</foo>
  <bar value="ipsum"></bar>

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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