5.2. Échappement

L'échappement est une méthode pour mettre entre guillemets un caractère isolément. L'échappement (\), avant un caractère, indique au shell d'interpréter littéralement ce caractère.

[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 particulières 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

produit une 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

La syntaxe $' ... ' de développement de chaînes de caractères échappées fournit un mécanisme d'affectation de caractères ASCII characters à des variables, à l'aide de valeurs octales ou hexadécimales, comme par exemple : quote=$'\042'.

Exemple 5.2. Caractères d'échappement

#!/bin/bash
# escaped.sh: caractères d'échappement

echo; echo

# Échapper un retour à la ligne.
# ------------------------------

echo ""

echo "Ceci s'affichera
sur deux lignes."
# Ceci s'affichera
# sur deux lignes.

echo "Ceci s'affichera \
sur une seul ligne."
# Ceci s'affichera sur une seule ligne.

echo; echo

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


echo "\v\v\v\v"      # Affiche \v\v\v\v litérallement.
# Utilisez l'option -e avec 'echo' pour afficher les caractères d'échappement.
echo "======================"
echo "TABULATIONS VERTICALES"
echo -e "\v\v\v\v"   # Affiche 4 tabulations verticales.
echo "======================="

echo "GUILLEMET DOUBLE"
echo -e "\042"       # Affiche " (guillemet, caractère octal ASCII 42).
echo "======================="

# La construction $'\X' rend l'option -e inutile.
echo; echo "RETOUR CHARIOT ET SON"
echo $'\n'           # Retour chariot.
echo $'\a'           # Alerte (son).

echo "======================="
echo "GUILLEMETS"
#  Les version 2 et ultérieures de Bash permettent l'utilisation de la
#+ construction $'\nnn'.
# Notez que, dans ce cas, '\nnn' est une valeur octale.
echo $'\t \042 \t'   # Guillemet (") entouré par des tabulations.

#  Cela fonctionne aussi avec des valeurs hexadécimales, dans une
#+ expression de type $'\xhhh'.
echo $'\t \x22 \t'  # Guillemet (") entouré par des tabulations.
# Merci, Greg Keraunen, de nous l'avoir indiqué.
# Les versions précédentes de Bash permettent '\x022'.
echo "======================="
echo


# Affecter des caractères ASCII à une variable.
# ----------------------------------------------
guillemet=$'\042'        # " affecté à une variable.
echo "$guillemet Ceci est un chaîne de caractères mise entre "\
"guillemets $guillemet, et ceci reste en dehors des guillemets."

echo

# Accoler des caractères ASCII dans une variable.
trois_soulignes=$'\137\137\137'  # 137 est le code octal ASCII pour '_'.
echo "$trois_soulignes SOULIGNE $trois_soulignes"

echo

ABC=$'\101\102\103\010'  # 101, 102, 103 sont les codes octaux de A, B, C.
echo $ABC

echo; echo

echappe=$'\033'                    # 033 est le code octal pour l'échappement.
echo "\"echappe\" s'affiche comme $echappe"
#                                   pas de sortie visible.

echo; echo

exit 0

Un exemple plus élaboré :

Exemple 5.3. Détecte les pressions sur le clavier

#!/bin/bash
# Auteur : Sigurd Solaas, 20 avril 2011
# Utilisé avec l'accord de l'auteur.
# Nécessite Bash version 4.2 ou supérieure.
# Traduction : Jean-Philippe Guérard

touche="pas encore de valeur"
while true; do
  clear
  echo "Démonstration des touches complémentaires avec Bash"
  echo "Appuyez sur une touche pour essayer :"
  echo
  echo "* Insérer, Supprimer, Début, Fin."
  echo "* Page suivante, Page précédente."
  echo "* Les 4 flèches."
  echo "* Tabulation, Entrée, Échappement, Espace."
  echo "* Des lettres, des chiffres, et cætera."
  echo
  echo "    d = afficher la date et l'heure"
  echo "    q = quitter"
  echo "================================"
  echo

 # Convertit les différentes touches Début vers
 # le Début de la touche 7 du pavé numérique.
 if [ "$touche" = $'\x1b\x4f\x48' ]; then
  touche=$'\x1b\x5b\x31\x7e'
  #   Expansion d'une chaîne de caractères.
 fi

 # Convertit les différentes touches Fin vers
 # le Fin de la touche 1 du pavé numérique.
 if [ "$touche" = $'\x1b\x4f\x46' ]; then
  touche=$'\x1b\x5b\x34\x7e'
 fi

 case "$touche" in
  $'\x1b\x5b\x32\x7e')  # Insérer
   echo Touche Insérer
  ;;
  $'\x1b\x5b\x33\x7e')  # Supprimer
   echo Touche Supprimer
  ;;
  $'\x1b\x5b\x31\x7e')  # Début (7 du pavé numérique)
   echo Touche Début
  ;;
  $'\x1b\x5b\x34\x7e')  # Fin (1 du pavé numérique)
   echo Touche Fin
  ;;
  $'\x1b\x5b\x35\x7e')  # Page précédente
   echo Touche Page précédente
  ;;
  $'\x1b\x5b\x36\x7e')  # Page suivante
   echo Touche Page suivante
  ;;
  $'\x1b\x5b\x41')  # Flèche vers le haut
   echo Touche Flèche vers le haut
  ;;
  $'\x1b\x5b\x42')  # Flèche vers le bas
   echo Touche Flèche vers le bas
  ;;
  $'\x1b\x5b\x43')  # Flèche vers la droite
   echo Touche Flèche vers la droite
  ;;
  $'\x1b\x5b\x44')  # Flèche vers la gauche
   echo Touche Flèche vers la gauche
  ;;
  $'\x09')  # Tabulation
   echo Touche Tabulation
  ;;
  $'\x0a')  # Entrée
   echo Touche Entrée
  ;;
  $'\x1b')  # Échappement
   echo Touche Échappement
  ;;
  $'\x20')  # Espace
   echo Touche Espace
  ;;
  d)
   date
  ;;
  q)
  echo Il est temps d\'arrêter...
  echo
  exit 0
  ;;
  *)
   echo Vous avez appuyé sur : \'"$touche"\'
  ;;
 esac

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

 unset T1 T2 T3
 read -s -N1 -p "Appuyez sur une touche : "
 T1="$REPLY"
 read -s -N2 -t 0.001
 T2="$REPLY"
 read -s -N1 -t 0.001
 T3="$REPLY"
 touche="$T1$T2$T3"

done

exit $?

Voir aussi l'Exemple 37.1, « Expansion d'une 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 qu'il est « auto-échappé », fortement protégé c'est-à-dire entre apostrophes ou guillemets simples (''), faiblement protégé c'est-à-dire entre guillemets doubles (""), qu'il apparaît dans une évaluation 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

                      #  Évaluation de commande
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 en lui-même ne peut 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 des mots dans la liste des arguments d'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 $liste_fichiers

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 -)
# Reprend la commande de copie de répertoires d'Alan Cox, mais séparée
# en deux lignes pour améliorer sa lisibilité.

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

Note

Si une ligne de script se termine par 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 interprété 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.