5.2. Échappement

Échapper est une méthode pour mettre entre guillemets un caractère seul. L'échappement (\) précédant un caractère dit au shell d'interpréter le caractère littéralement.

[Attention]

Attention

Avec certaines commandes et utilitaires, tels que echo et sed, échapper un caractère peut avoir l'effet inverse - cela peut activer un comportement particulier pour ce caractère.

Significations spéciales des caractères échappés

utilisé avec echo et sed
\n

passe à la ligne

\r

renvoie le curseur en début de ligne

\t

tabulation

\v

tabulation verticale

\b

retour en arrière

\a

signifie alerte (sonore ou visuelle)

\0xx

Transcode en octal le caractère dont le code ASCII est 0nn, dans lequel nn est une suite de chiffres.

[Important]

Important

DIFF63

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'.

Exemple 5.2. Caractères d'échappement

&escaped;

Un exemple plus élaboré :

Exemple 5.3. Détecte les pressions du clavier

#!/bin/bash
# Author: Sigurd Solaas, 20 Apr 2011
# Used in ABS Guide with permission.
# Requires version 4.2+ of Bash.

key="no value yet"
while true; do
  clear
  echo "Bash Extra Keys Demo. Keys to try:"
  echo
  echo "* Insert, Delete, Home, End, Page_Up and Page_Down"
  echo "* The four arrow keys"
  echo "* Tab, enter, escape, and space key"
  echo "* The letter and number keys, etc."
  echo
  echo "    d = show date/time"
  echo "    q = quit"
  echo "================================"
  echo

 # Convert the separate home-key to home-key_num_7:
 if [ "$key" = $'\x1b\x4f\x48' ]; then
  key=$'\x1b\x5b\x31\x7e'
  #   Quoted string-expansion construct. 
 fi

 # Convert the separate end-key to end-key_num_1.
 if [ "$key" = $'\x1b\x4f\x46' ]; then
  key=$'\x1b\x5b\x34\x7e'
 fi

 case "$key" in
  $'\x1b\x5b\x32\x7e')  # Insert
   echo Insert Key
  ;;
  $'\x1b\x5b\x33\x7e')  # Delete
   echo Delete Key
  ;;
  $'\x1b\x5b\x31\x7e')  # Home_key_num_7
   echo Home Key
  ;;
  $'\x1b\x5b\x34\x7e')  # End_key_num_1
   echo End Key
  ;;
  $'\x1b\x5b\x35\x7e')  # Page_Up
   echo Page_Up
  ;;
  $'\x1b\x5b\x36\x7e')  # Page_Down
   echo Page_Down
  ;;
  $'\x1b\x5b\x41')  # Up_arrow
   echo Up arrow
  ;;
  $'\x1b\x5b\x42')  # Down_arrow
   echo Down arrow
  ;;
  $'\x1b\x5b\x43')  # Right_arrow
   echo Right arrow
  ;;
  $'\x1b\x5b\x44')  # Left_arrow
   echo Left arrow
  ;;
  $'\x09')  # Tab
   echo Tab Key
  ;;
  $'\x0a')  # Enter
   echo Enter Key
  ;;
  $'\x1b')  # Escape
   echo Escape Key
  ;;
  $'\x20')  # Space
   echo Space Key
  ;;
  d)
   date
  ;;
  q)
  echo Time to quit...
  echo
  exit 0
  ;;
  *)
   echo You pressed: \'"$key"\'
  ;;
 esac

 echo
 echo "================================"

 unset K1 K2 K3
 read -s -N1 -p "Press a key: "
 K1="$REPLY"
 read -s -N2 -t 0.001
 K2="$REPLY"
 read -s -N1 -t 0.001
 K3="$REPLY"
 key="$K1$K2$K3"

done

exit $?

Voir aussi l'Exemple 37.1, « Expansion de chaîne de caractères ».

\"

rend au guillemet sa signification littérale

echo "Bonjour"                    # Bonjour
echo "\"Bonjour\" ..., dit-il."  # "Bonjour" ..., dit-il.
\$

rend au dollar sa signification littérale (un nom de variable suivant un \$ ne sera pas référencé)

echo "\$variable01"  # $variable01
echo "Ce livre coûte \$7.98." # Ce livre coûte $7.98.
\\

donne à l'antislash sa signification littérale

echo "\\"  # donne \

# Alors que...

echo "\"   # Appelle une deuxième invite de la ligne de commande.
           # Dans un script, donne un message d'erreur.

# Cependant...

echo '\'   # Donne \
[Note]

Note

Le comportement de \ varie suivant s'il est « auto-échappé », fortement protégé c'est-à-dire entre apostrophes ou guillemets simples (''), faiblement protégé c'est-à-dire entre guillemets doubles (""), s'il apparaît dans une substitution de commande ou dans un document en ligne.

                      #  Simple échappement et mise entre guillemets
echo \z               #  z
echo \\z              # \z
echo '\z'             # \z
echo '\\z'            # \\z
echo "\z"             # \z
echo "\\z"            # \z

                      #  Substitution de commandes
echo `echo \z`        #  z
echo `echo \\z`       #  z
echo `echo \\\z`      # \z
echo `echo \\\\z`     # \z
echo `echo \\\\\\z`   # \z
echo `echo \\\\\\\z`  # \\z
echo `echo "\z"`      # \z
echo `echo "\\z"`     # \z

                      # Document en ligne
cat <<EOF
\z
EOF                   # \z

cat <<EOF
\\z
EOF                   # \z

#  Les exemples ci-dessus ont été fournis par Stéphane
#+ Chazelas.

Les éléments d'une chaîne de caractères affectée à une variable peuvent être échappés, mais le caractère d'échappement seul ne doit pas être affecté à une variable.

variable=\
echo "$variable"
# Ne fonctionne pas et donne le message d'erreur :
# test.sh: : command not found
# Un caractère d'échappement "nu" ne peut être affecté correctement à une variable.
#
#  Ce qui arrive ici est que "\" échappe le saut de ligne et
#+ l'effet est          variable=echo "$variable"
#+                      affectation invalide de variable

variable=\
23skidoo
echo "$variable"        #  23skidoo
                        #  Ceci fonctionne car la deuxième ligne est une affectation
                        #+ valide de variable.

variable=\
#        \^    échappement suivi d'un espace
echo "$variable"        # espace

variable=\\
echo "$variable"        # \

variable=\\\
echo "$variable"
# Ne fonctionnera pas et donne le message d'erreur :
# test.sh: \: command not found
#
#  La première séquence d'échappement échappe la deuxième, mais la troisième est laissée
#+ seule avec le même résultat que dans le premier exemple ci-dessus.

variable=\\\\
echo "$variable"        # \\
                        # Deuxième et quatrième séquences d'échappement
                        # Ça marche.

Échapper un espace peut bloquer la séparation de mots dans une liste d'arguments pour une commande.

liste_fichiers="/bin/cat /bin/gzip /bin/more /usr/bin/less /usr/bin/emacs-20.7"
      # Liste de fichiers comme argument(s) d'une commande.

      # On demande de tout lister, avec deux fichiers en plus.
      ls -l /usr/X11R6/bin/xsetroot /sbin/dump $file_list

      echo "-------------------------------------------------------------------------"

      # Qu'arrive-t'il si nous échappons un ensemble d'espaces ?
      ls -l /usr/X11R6/bin/xsetroot\ /sbin/dump\ $file_list
      # Erreur: les trois premiers fichiers sont concaténés en un seul argument pour 'ls -l'
      # parce que les deux espaces échappés empêchent la séparation des arguments.

L'échappement permet également d'écrire une commande sur plusieurs lignes. Normalement, chaque ligne séparée constitue une commande différente mais un échappement à la fin d'une ligne échappe le caractère de saut de ligne, et la séquence de la commande continue sur la ligne suivante.

(cd /source/repertoire && tar cf - . ) | \
(cd /dest/repertoire && tar xpvf -)
# Répétant la commande de copie de répertoires d'Alan Cox, mais séparée en deux lignes
# pour accroître la lisibilité.

# Comme alternative :
tar cf - -C /source/directory . |
tar xpvf - -C /dest/directory
# Voir note ci-dessous.
# (Merci à Stéphane Chazelas.)
[Note]

Note

Si la ligne d'un script termine avec un |, le caractère tube, alors il n'est pas strictement nécessaire de mettre un échappement \. Il est néanmoins considéré comme une bonne pratique de programmation de toujours échapper une ligne de code qui continue sur la ligne suivante.

echo "foo
bar"
#foo
#bar

echo

echo 'foo
bar'    # Pas encore de différence.
#foo
#bar

echo

echo foo\
bar     # Saut de ligne échappé.
#foobar

echo

echo "foo\
bar"     #  Pareil ici, car \ toujours interpreté comme un échappement à l'intérieur de
         #  guillemets faibles.
#foobar

echo

echo 'foo\
bar'     # Le caractère d'échappement \ est pris littéralement à cause des guillemets forts.
#foo\
#bar

# Exemples suggérés par Stéphane Chazelas.