28

I'm new to Bash scripting, and this here is just puzzling to me. I'm adding ASCII art to a project, and can't seem to figure out how to escape certain characters. Would someone please help me get the following code below to work?

Whenever I tried adding slashes as escape characters to fix the errors, the slashes also wound up printing to console on execution. This ruins the image. I don't understand what I'm doing wrong, so I've posted the code below in the hopes that someone will take a moment to show me the right way. Please? I've removed the quotes to prevent more clutter.

echo -en "\E[31m"
echo
echo       _,.
echo     ,` -.)
echo    '( _/'-\\-.              
echo   /,|`--._,-^|          ,    
echo   \_| |`-._/||          ,'|      
echo     |  `-, / |         /  /     
echo     |     || |        /  /      
echo      `r-._||/   __   /  / 
echo  __,-<_     )`-/  `./  /
echo '  \   `---'   \   /  /
echo     |           |./  / 
echo     /           //  /    
echo \_/' \         |/  /        
echo  |    |   _,^-'/  /             
echo  |    , ``  (\/  /_       
echo   \,.->._    \X-=/^        
echo   (  /   `-._//^` 
echo    `Y-.____(__}             
echo     |     {__)          
echo           ()`    
that other guy
  • 116,971
  • 11
  • 170
  • 194
user3698316
  • 427
  • 1
  • 4
  • 7

2 Answers2

91

Quotes in bash are important syntactic elements, not clutter. However, to print ASCII art, save yourself the trouble of proper quoting and escaping and just use a here document:

cat << "EOF"
       _,.
     ,` -.)
    '( _/'-\\-.               
   /,|`--._,-^|            ,     
   \_| |`-._/||          ,'|       
     |  `-, / |         /  /      
     |     || |        /  /       
      `r-._||/   __   /  /  
  __,-<_     )`-/  `./  /
 '  \   `---'   \   /  / 
     |           |./  /  
     /           //  /     
 \_/' \         |/  /         
  |    |   _,^-'/  /              
  |    , ``  (\/  /_        
   \,.->._    \X-=/^         
   (  /   `-._//^`  
    `Y-.____(__}              
     |     {__)           
           ()`     
EOF

Make sure not to remove the quotes here. They are not optional.

Eric Majerus
  • 1,099
  • 1
  • 12
  • 23
that other guy
  • 116,971
  • 11
  • 170
  • 194
  • 2
    Quotes on first delimiting identifier (i.e : "EOF") is necessary because it considers whole thing as text and special meaning of backslash,quotes and backticks will not come into picture. – ns15 Jun 08 '17 at 08:16
  • 2
    I got "unexpected end of file" when running this in my bash script. It was solved by removing all spaces before the closing EOF. https://stackoverflow.com/questions/19986541/error-when-using-a-bash-here-doc-unexpected-end-of-file#answer-19986600 – Eric Majerus Sep 18 '17 at 20:51
  • Saved by the quotes around `EOF` Thanks! – n0nag0n Jun 29 '20 at 22:22
  • Doesn't work. The bash script doesn't open, im on win 10 – Smooth Neon Apr 15 '21 at 13:17
  • @SmoothNeon What does it mean for a bash script to open? Are you running it from a terminal? How? What does it say? – that other guy Apr 15 '21 at 16:23
  • I meant it's closing immediately after executing. From my observations "EOF" makes it behave that way. Luckily I found a simpler solution for this. Create a new text file (.txt and .ASC extensions are the best for ascii), paste your ascii art inside the text file and save it, now in batch file you must link that file using "type FILE.txt". Thats all, your art should appear and you also saved some space because ascii art is in another file (so it's not cluttering the script). – Smooth Neon Apr 18 '21 at 18:06
  • Your system is set up to close the terminal when the script exits. It's not really a bash issue, and you'll see that running the script manually from a terminal works fine. You can add `read -n 1 -p "Press any key to close"` at the end of the script to work around this – that other guy Apr 18 '21 at 22:26
  • Oh nevermind... I meant batch, not bash :) – Smooth Neon Apr 22 '21 at 08:54
1

echo takes a series of arguments. If you type

echo  foo      bar

the echo command gets two arguments, "foo" and "bar", and the spacing between the words is discarded.

For what you're trying to do, you probably want echo to receive exactly one argument for each line. In bash, the easiest way is probably to use so-called "ANSI-C Quoting". Within each string, each apostrophe ' and backslash \ character has to be escaped with a backslash.

Here's a version of your script using this method:

#!/bin/bash

echo -n $'\E[31m'
echo $''
echo $'      _,.'
echo $'    ,` -.)'
echo $'   \'( _/\'-\\\\-.'
echo $'  /,|`--._,-^|          ,'
echo $'  \\_| |`-._/||          ,\'|'
echo $'    |  `-, / |         /  /'
echo $'    |     || |        /  /'
echo $'     `r-._||/   __   /  /'
echo $' __,-<_     )`-/  `./  /'
echo $'\'  \\   `---\'   \\   /  /'
echo $'    |           |./  /'
echo $'    /           //  /'
echo $'\\_/\' \\         |/  /'
echo $' |    |   _,^-\'/  /'
echo $' |    , ``  (\\/  /_'
echo $'  \\,.->._    \\X-=/^'
echo $'  (  /   `-._//^`'
echo $'   `Y-.____(__}'
echo $'    |     {__)'
echo $'          ()`'

(The added backslashes do mess up the picture in the script, but it appears correctly on output.)

For this case, that other guy's answer is a better approach, since it avoids the need to escape any of the special characters, but this technique could be useful for smaller output.

Or you could just put the raw picture into a file and cat it to standard output.

Community
  • 1
  • 1
Keith Thompson
  • 254,901
  • 44
  • 429
  • 631