5. Guillemets et apostrophes

Encadrer une chaîne de caractères avec des apostrophes a pour effet de protéger les caractères spéciaux et d'empêcher leur réinterprétation ou expansion par le shell ou par un script shell. Un caractère est « spécial » si son interprétation a une autre signification que la chaîne elle-même, comme par exemple le caractère joker *.

bash$ ls -l [Vv]*
-rw-rw-r--    1 bozo  bozo       324 Apr  2 15:05 VIEWDATA.BAT
 -rw-rw-r--    1 bozo  bozo       507 May  4 14:25 vartrace.sh
 -rw-rw-r--    1 bozo  bozo       539 Apr 14 17:11 viewdata.sh


bash$ ls -l '[Vv]*'
ls: [Vv]*: No such file or directory

Certains programmes et utilitaires réinterprètent ou étendent les caractères spéciaux placés dans une chaîne de caractères entre apostrophes. Une fonction importante des apostrophes est donc de protéger du shell les paramètres dans une ligne de commande, tout en laissant au programme appelé la possibilité de les étendre et réinterpréter.

bash$ grep '[Pp]remière' *.txt
fichier1.txt:C'est la première ligne de fichier1.txt.
fichier2.txt:C'est la Première ligne de fichier2.txt.

Notez que la version sans apostrophes grep [Pp]remière *.txt fonctionne avec le shell Bash. [24]

Les guillemets peuvent supprimer l'appétit d'echo pour les nouvelles lignes.

bash$ echo $(ls -l)
total 8 -rw-rw-r-- 1 bo bo 13 Aug 21 12:57 t.sh -rw-rw-r-- 1 bo bo 78 Aug 21 12:57 u.sh


bash$ echo "$(ls -l)"
total 8
 -rw-rw-r--  1 bo bo  13 Aug 21 12:57 t.sh
 -rw-rw-r--  1 bo bo  78 Aug 21 12:57 u.sh

5.1. Placer les variables entre guillemets

Lors du référencement d'une variable, il est généralement conseillé de placer son nom entre guillemets. Cela empêche la réinterprétation de tous les caractères spéciaux à l'intérieur de la chaîne -- le nom de la variable [25] -- sauf $, ` (apostrophe inversée) et \ (échappement). [26] Comme $ reste interprété comme un caractère spécial, cela permet de référencer une variable entre guillemets ("$variable"), c'est-à-dire de remplacer la variable par sa valeur (voir plus haut l'Exemple 4.1, « Affectation de variable et substitution  »).

Vous pouvez utiliser les guillemets pour éviter la séparation de mots. [27] Un argument compris entre guillemets se présente comme un seul mot, même s'il contient des espaces blancs.

Liste="un deux trois"

for a in $Liste    #  Divise la variable en plusieurs parties
                   #+ en utilisant les espaces blancs comme séparateur.
do
  echo "$a"
done
# un
# deux
# trois

echo "---"

for a in "$Liste"  # Préserve les espaces blancs dans une seule variable.
do #     ^     ^
  echo "$a"
done
# un deux trois

Un exemple plus élaboré :

variable1="une variable contenant cinq mots"
COMMANDE Ceci est $variable1    # Exécute COMMANDE avec sept arguments :
# "Ceci" "est" "une" "variable" "contenant" "cinq" "mots"

COMMANDE "Ceci est $variable1"  # Exécute COMMANDE avec un argument :
# "Ceci est une variable contenant cinq mots"


variable2=""    # Vide.

COMMANDE $variable2 $variable2 $variable2
    # Exécute COMMANDE sans arguments.
COMMANDE "$variable2" "$variable2" "$variable2"
    # Exécute COMMANDE avec trois arguments vides.
COMMANDE "$variable2 $variable2 $variable2"
    # Exécute COMMANDE avec un argument (deux espaces).

# Merci, Stéphane Chazelas.
[Astuce]

Astuce

Mettre les arguments d'une instruction echo entre guillemets est nécessaire seulement lorsque la séparation de mots ou la préservation d'espaces blancs pose problème.

Exemple 5.1. Afficher des variables bizarres

#!/bin/bash
# weirdvars.sh : Affiche des variables bizarres.

var="'(]\\{}\$\""
echo $var        # '(]\{}$"
echo "$var"      # '(]\{}$"     Ne fait pas de différence.

echo

IFS='\'
echo $var        # '(] {}$"     \ converti en espace. Pourquoi ?
echo "$var"      # '(]\{}$"

# Exemples ci-dessus donnés par Stéphane Chazelas.

exit 0

Les apostrophes (' ') opèrent de manière similaire aux guillemets mais ne permettent pas de référencer des variables car la signification spéciale de $ est désactivée. À l'intérieur des apostrophes, tous les caractères spéciaux autres que ' sont interprétés littéralement. Vous pouvez considérer que les apostrophes (« citation totale ») sont une façon plus stricte de protéger que les guillemets (« citation partielle »).

[Note]

Note

Même le caractère d'échappement (\) aboutit à une interprétation littérale avec les apostrophes.

echo "Pourquoi ne puis-je pas écrire le caractère ' avec des apostrophes"

echo

# la méthode de contournement:
echo 'Pourquoi ne puis-je pas écrire le caractère '\' "'" ' avec une apostrophe'
#    |--------------------------------------------|  |----------------------------|
# Deux chaînes chacune avec apostrophes, et, intercalés, des apostrophes.

# Exemple de Stéphane Chazelas.


[24] Sauf s'il existe un fichier nommé first dans le répertoire courant. Encore une autre raison pour placer des guillemets (merci pour cette indication, Harald Koenig).

[25] Cela a aussi des effets de bord sur la valeur de la variable (voir ci-dessous)

[26] Entourer « ! » par des guillemets donne une erreur lorsque cette construction est utilisée à partir de la ligne de commande. Ceci est interprété comme une commande d'historique. À l'intérieur d'un script, ce problème ne survient pas car le mécanisme d'historique de Bash est désactivé.

Un problème plus ennuyeux concerne le comportement apparemment incohérent de « \ » à l'intérieur de guillemets.

bash$ echo bonjour\!
bonjour!


bash$ echo "bonjour\!"
bonjour\!




bash$ echo -e x\ty
xty


bash$ echo -e "x\ty"
x       y
              

What happens is that double quotes normally escape the « \ » escape character, so that it echoes literally. However, the -e option to echo changes that. It causes the « \t » to be interpreted as a tab.

(Merci, Wayne Pollock, de nous l'avoir indiqué et Geoff Lee, de nous l'avoir expliqué.)

[27] Ici, la « séparation de mots  » signifie que la chaîne de caractères est divisée en un certain nombre d'arguments séparés : un par mot.