Advanced Bash-Scripting Guide: An in-depth exploration of the art of shell scripting
Prev | Chapter 5. Quoting | Next

# 5.2. Escaping

Escaping is a method of quoting single characters. The escape (\) preceding a character tells the shell to interpret that character literally.

| With certain commands and utilities, such as echo and sed, escaping a character may have the opposite effect - it can toggle on a special meaning for that character.

Special meanings of certain escaped characters

used with echo and sed

\n

  means newline

\r

  means return

\t

  means tab

\v

  means vertical tab

\b

  means backspace

\a

  means alert (beep or flash)

\0xx

  translates to the octal ASCII equivalent of `0nn`, where `nn` is a string of digits

  | The `$' ... '` quoted string-expansion construct is a mechanism that uses escaped octal or hex values to assign ASCII characters to variables, e.g., quote=$'\042'.

  Example 5-2. Escaped Characters

         1 #!/bin/bash
         2 # escaped.sh: escaped characters
         3
         4 #############################################################
         5 ### First, let's show some basic escaped-character usage. ###
         6 #############################################################
         7
         8 # Escaping a newline.
         9 # ------------------
        10
        11 echo ""
        12
        13 echo "This will print
        14 as two lines."
        15 # This will print
        16 # as two lines.
        17
        18 echo "This will print \
        19 as one line."
        20 # This will print as one line.
        21
        22 echo; echo
        23
        24 echo "============="
        25
        26
        27 echo "\v\v\v\v"      # Prints \v\v\v\v literally.
        28 # Use the -e option with 'echo' to print escaped characters.
        29 echo "============="
        30 echo "VERTICAL TABS"
        31 echo -e "\v\v\v\v"   # Prints 4 vertical tabs.
        32 echo "=============="
        33
        34 echo "QUOTATION MARK"
        35 echo -e "\042"       # Prints " (quote, octal ASCII character 42).
        36 echo "=============="
        37
        38
        39
        40 # The $'\X' construct makes the -e option unnecessary.
        41
        42 echo; echo "NEWLINE and (maybe) BEEP"
        43 echo $'\n'           # Newline.
        44 echo $'\a'           # Alert (beep).
        45                      # May only flash, not beep, depending on terminal.
        46
        47 # We have seen $'\nnn" string expansion, and now . . .
        48
        49 # =================================================================== #
        50 # Version 2 of Bash introduced the $'\nnn' string expansion construct.
        51 # =================================================================== #
        52
        53 echo "Introducing the \$\' ... \' string-expansion construct . . . "
        54 echo ". . . featuring more quotation marks."
        55
        56 echo $'\t \042 \t'   # Quote (") framed by tabs.
        57 # Note that  '\nnn' is an octal value.
        58
        59 # It also works with hexadecimal values, in an $'\xhhh' construct.
        60 echo $'\t \x22 \t'  # Quote (") framed by tabs.
        61 # Thank you, Greg Keraunen, for pointing this out.
        62 # Earlier Bash versions allowed '\x022'.
        63
        64 echo
        65
        66
        67 # Assigning ASCII characters to a variable.
        68 # ----------------------------------------
        69 quote=$'\042'        # " assigned to a variable.
        70 echo "$quote Quoted string $quote and this lies outside the quotes."
        71
        72 echo
        73
        74 # Concatenating ASCII chars in a variable.
        75 triple_underline=$'\137\137\137'  # 137 is octal ASCII code for '_'.
        76 echo "$triple_underline UNDERLINE $triple_underline"
        77
        78 echo
        79
        80 ABC=$'\101\102\103\010'           # 101, 102, 103 are octal A, B, C.
        81 echo $ABC
        82
        83 echo
        84
        85 escape=$'\033'                    # 033 is octal for escape.
        86 echo "\"escape\" echoes as $escape"
        87 #                                   no visible output.
        88
        89 echo
        90
        91 exit 0

  A more elaborate example:

  Example 5-3. Detecting key-presses

         1 #!/bin/bash
         2 # Author: Sigurd Solaas, 20 Apr 2011
         3 # Used in ABS Guide with permission.
         4 # Requires version 4.2+ of Bash.
         5
         6 key="no value yet"
         7 while true; do
         8   clear
         9   echo "Bash Extra Keys Demo. Keys to try:"
        10   echo
        11   echo "* Insert, Delete, Home, End, Page_Up and Page_Down"
        12   echo "* The four arrow keys"
        13   echo "* Tab, enter, escape, and space key"
        14   echo "* The letter and number keys, etc."
        15   echo
        16   echo "    d = show date/time"
        17   echo "    q = quit"
        18   echo "================================"
        19   echo
        20
        21  # Convert the separate home-key to home-key_num_7:
        22  if [ "$key" = $'\x1b\x4f\x48' ]; then
        23   key=$'\x1b\x5b\x31\x7e'
        24   #   Quoted string-expansion construct.
        25  fi
        26
        27  # Convert the separate end-key to end-key_num_1.
        28  if [ "$key" = $'\x1b\x4f\x46' ]; then
        29   key=$'\x1b\x5b\x34\x7e'
        30  fi
        31
        32  case "$key" in
        33   $'\x1b\x5b\x32\x7e')  # Insert
        34    echo Insert Key
        35   ;;
        36   $'\x1b\x5b\x33\x7e')  # Delete
        37    echo Delete Key
        38   ;;
        39   $'\x1b\x5b\x31\x7e')  # Home_key_num_7
        40    echo Home Key
        41   ;;
        42   $'\x1b\x5b\x34\x7e')  # End_key_num_1
        43    echo End Key
        44   ;;
        45   $'\x1b\x5b\x35\x7e')  # Page_Up
        46    echo Page_Up
        47   ;;
        48   $'\x1b\x5b\x36\x7e')  # Page_Down
        49    echo Page_Down
        50   ;;
        51   $'\x1b\x5b\x41')  # Up_arrow
        52    echo Up arrow
        53   ;;
        54   $'\x1b\x5b\x42')  # Down_arrow
        55    echo Down arrow
        56   ;;
        57   $'\x1b\x5b\x43')  # Right_arrow
        58    echo Right arrow
        59   ;;
        60   $'\x1b\x5b\x44')  # Left_arrow
        61    echo Left arrow
        62   ;;
        63   $'\x09')  # Tab
        64    echo Tab Key
        65   ;;
        66   $'\x0a')  # Enter
        67    echo Enter Key
        68   ;;
        69   $'\x1b')  # Escape
        70    echo Escape Key
        71   ;;
        72   $'\x20')  # Space
        73    echo Space Key
        74   ;;
        75   d)
        76    date
        77   ;;
        78   q)
        79   echo Time to quit...
        80   echo
        81   exit 0
        82   ;;
        83   *)
        84    echo You pressed: \'"$key"\'
        85   ;;
        86  esac
        87
        88  echo
        89  echo "================================"
        90
        91  unset K1 K2 K3
        92  read -s -N1 -p "Press a key: "
        93  K1="$REPLY"
        94  read -s -N2 -t 0.001
        95  K2="$REPLY"
        96  read -s -N1 -t 0.001
        97  K3="$REPLY"
        98  key="$K1$K2$K3"
        99
       100 done
       101
       102 exit $?

  See also Example 37-1.

\"

  gives the quote its literal meaning

         1 echo "Hello"                     # Hello
         2 echo "\"Hello\" ... he said."    # "Hello" ... he said.

\$

  gives the dollar sign its literal meaning (variable name following \$ will not be referenced)

         1 echo "\$variable01"           # $variable01
         2 echo "The book cost \$7.98."  # The book cost $7.98.

\\

  gives the backslash its literal meaning

         1 echo "\\"  # Results in \
         2
         3 # Whereas . . .
         4
         5 echo "\"   # Invokes secondary prompt from the command-line.
         6            # In a script, gives an error message.
         7
         8 # However . . .
         9
        10 echo '\'   # Results in \

The behavior of \ depends on whether it is escaped, strong-quoted, weak-quoted, or appearing within command substitution or a here document.

       1                       #  Simple escaping and quoting
       2 echo \z               #  z
       3 echo \\z              # \z
       4 echo '\z'             # \z
       5 echo '\\z'            # \\z
       6 echo "\z"             # \z
       7 echo "\\z"            # \z
       8
       9                       #  Command substitution
      10 echo `echo \z`        #  z
      11 echo `echo \\z`       #  z
      12 echo `echo \\\z`      # \z
      13 echo `echo \\\\z`     # \z
      14 echo `echo \\\\\\z`   # \z
      15 echo `echo \\\\\\\z`  # \\z
      16 echo `echo "\z"`      # \z
      17 echo `echo "\\z"`     # \z
      18
      19                       # Here document
      20 cat <<EOF
      21 \z
      22 EOF                   # \z
      23
      24 cat <<EOF
      25 \\z
      26 EOF                   # \z
      27
      28 # These examples supplied by Stéphane Chazelas.

Elements of a string assigned to a variable may be escaped, but the escape character alone may not be assigned to a variable.

       1 variable=\
       2 echo "$variable"
       3 # Will not work - gives an error message:
       4 # test.sh: : command not found
       5 # A "naked" escape cannot safely be assigned to a variable.
       6 #
       7 #  What actually happens here is that the "\" escapes the newline and
       8 #+ the effect is        variable=echo "$variable"
       9 #+                      invalid variable assignment
      10
      11 variable=\
      12 23skidoo
      13 echo "$variable"        #  23skidoo
      14                         #  This works, since the second line
      15                         #+ is a valid variable assignment.
      16
      17 variable=\
      18 #        \^    escape followed by space
      19 echo "$variable"        # space
      20
      21 variable=\\
      22 echo "$variable"        # \
      23
      24 variable=\\\
      25 echo "$variable"
      26 # Will not work - gives an error message:
      27 # test.sh: \: command not found
      28 #
      29 #  First escape escapes second one, but the third one is left "naked",
      30 #+ with same result as first instance, above.
      31
      32 variable=\\\\
      33 echo "$variable"        # \\
      34                         # Second and fourth escapes escaped.
      35                         # This is o.k.

Escaping a space can prevent word splitting in a command's argument list.

       1 file_list="/bin/cat /bin/gzip /bin/more /usr/bin/less /usr/bin/emacs-20.7"
       2 # List of files as argument(s) to a command.
       3
       4 # Add two files to the list, and list all.
       5 ls -l /usr/X11R6/bin/xsetroot /sbin/dump $file_list
       6
       7 echo "-------------------------------------------------------------------------"
       8
       9 # What happens if we escape a couple of spaces?
      10 ls -l /usr/X11R6/bin/xsetroot\ /sbin/dump\ $file_list
      11 # Error: the first three files concatenated into a single argument to 'ls -l'
      12 #        because the two escaped spaces prevent argument (word) splitting.

The escape also provides a means of writing a multi-line command. Normally, each separate line constitutes a different command, but an escape at the end of a line escapes the newline character, and the command sequence continues on to the next line.

       1 (cd /source/directory && tar cf - . ) | \
       2 (cd /dest/directory && tar xpvf -)
       3 # Repeating Alan Cox's directory tree copy command,
       4 # but split into two lines for increased legibility.
       5
       6 # As an alternative:
       7 tar cf - -C /source/directory . |
       8 tar xpvf - -C /dest/directory
       9 # See note below.
      10 # (Thanks, Stéphane Chazelas.)

| If a script line ends with a |, a pipe character, then a \, an escape, is not strictly necessary. It is, however, good programming practice to always escape the end of a line of code that continues to the following line.

       1 echo "foo
       2 bar"
       3 #foo
       4 #bar
       5
       6 echo
       7
       8 echo 'foo
       9 bar'    # No difference yet.
      10 #foo
      11 #bar
      12
      13 echo
      14
      15 echo foo\
      16 bar     # Newline escaped.
      17 #foobar
      18
      19 echo
      20
      21 echo "foo\
      22 bar"     # Same here, as \ still interpreted as escape within weak quotes.
      23 #foobar
      24
      25 echo
      26
      27 echo 'foo\
      28 bar'     # Escape character \ taken literally because of strong quoting.
      29 #foo\
      30 #bar
      31
      32 # Examples suggested by Stéphane Chazelas.

Prev | Home | Next
Quoting | Up | Exit and Exit Status