I need to write some complex xml to a variable inside a bash script. The xml needs to be readable inside the bash script as this is where the xml fragment will live, it's not being read from another file or source.

So my question is this if I have a long string which I want to be human readable inside my bash script what is the best way to go about it?

Ideally I want:

  • to not have to escape any of the characters
  • have it break across multiple lines making it human readable
  • keep it's indentation

Can this be done with EOF or something, could anyone give me an example?

e.g.

String = <<EOF
 <?xml version="1.0" encoding='UTF-8'?>
 <painting>
   <img src="madonna.jpg" alt='Foligno Madonna, by Raphael'/>
   <caption>This is Raphael's "Foligno" Madonna, painted in
   <date>1511</date>-<date>1512</date>.</caption>
 </painting>
EOF
link|improve this question

56% accept rate
feedback

2 Answers

up vote 14 down vote accepted

This will put your text into your variable without needing to escape the quotes. It will also handle unbalanced quotes (apostrophes). Putting quotes around the sentinal (EOF) prevents the text from undergoing parameter expansion. The -d'' causes it to read multiple lines (ignore newlines). read is a Bash built-in so it doesn't require calling an external command such as cat.

read -d '' String <<"EOF"
<?xml version="1.0" encoding='UTF-8'?>
 <painting>
   <img src="madonna.jpg" alt='Foligno Madonna, by Raphael'/>
   <caption>This is Raphael's "Foligno" Madonna, painted in
   <date>1511</date>-<date>1512</date>.</caption>
 </painting>
EOF
link|improve this answer
1  
+1 for avoiding cat. – James Sneeringer Oct 8 '09 at 14:05
I think avoiding cat is not an advantage here. At least you save some characters by using it. ;) – joschi Oct 8 '09 at 21:14
cat is an external command. Not using it saves doing that. Plus, some have the philosophy that if you're using cat with fewer than two arguments "Ur doin' it wrong" (which is distinct from "useless use of cat"). – Dennis Williamson Oct 9 '09 at 0:03
This doesn't work for me unless I put a space between -d and '' -- presumably because it doesn't realize there's an empty string after -d unless it's technically a separate parameter. This may also depend on what version of bash you have (I'm using 3.2.17 under Mac OS X v10.5.8). – Gordon Davisson Oct 9 '09 at 2:54
You're right about the -d needing a space after it. I may have typo'd that. I've fixed it now. – Dennis Williamson Oct 9 '09 at 6:04
show 1 more comment
feedback

You've been almost there. Either you use cat for the assembly of your string or you quote the whole string (in which case you'd have to escape the quotes inside your string):

#!/bin/sh
VAR1=$(cat <<EOF
<?xml version="1.0" encoding='UTF-8'?>
<painting>
  <img src="madonna.jpg" alt='Foligno Madonna, by Raphael'/>
  <caption>This is Raphael's "Foligno" Madonna, painted in
  <date>1511</date>-<date>1512</date>.</caption>
</painting>
EOF
)

VAR2="<?xml version=\"1.0\" encoding='UTF-8'?>
<painting>
  <img src=\"madonna.jpg\" alt='Foligno Madonna, by Raphael'/>
  <caption>This is Raphael's \"Foligno\" Madonna, painted in
  <date>1511</date>-<date>1512</date>.</caption>
</painting>"

echo "${VAR1}"
echo "${VAR2}"
link|improve this answer
Unfortunately, the apostrophe in "Raphael's" makes the first one not work. – Dennis Williamson Oct 8 '09 at 12:37
Both assignments work for me eventually. The single quote in VAR1 should not be a problem (at least not for bash). Maybe you have been misled by the syntax highlighting? – joschi Oct 8 '09 at 21:13
It works in a script, but not at a Bash prompt. Sorry for not being clearer. – Dennis Williamson Oct 9 '09 at 6:08
feedback

Your Answer

 
or
required, but never shown

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