Tell me more ×
Server Fault is a question and answer site for professional system and network administrators. It's 100% free, no registration required.

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
share|improve this question

3 Answers

up vote 36 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
share|improve this answer
4  
+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
2  
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
2  
and never ever indent second EOF.... (multiple table to head bangs involved) – troyaner May 18 '12 at 19:40
1  
I tried to use the above statement while set -e. It seems read always returns non-zero. You can thick this behaviour by using ! read -d ....... – krissi Nov 8 '12 at 10:56
show 11 more comments

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}"
share|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
#!/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
`
echo "VAR1: ${VAR1}"

This should work fine within Bourne shell environment

share|improve this answer
+1 this solution allow variable substitution like ${foo} – Offirmo Sep 27 '12 at 16:54

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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