5. Guillemets et apostrophes

Encadrer une chaîne de caractères par des apostrophes a pour effet de protéger les caractères spéciaux de la chaîne en empêchant leur réinterprétation ou leur expansion par le shell ou par un script shell. (Un caractère est « spécial » s'il a une autre interprétation possible en plus de sa valeur littérale. Par exemple, l'astérisque * représente le caractère joker dans le remplacement et dans le expressions rationnelles.)

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 développent les caractères spéciaux situé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 d'une ligne de commande, tout en laissant au programme appelé la possibilité de les développer et de les 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.

Remarque : la version sans apostrophes grep [Pp]remière *.txt fonctionne avec le shell Bash. [28]

Les guillemets savent couper l'appétit d'echo pour les sauts de 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 des variables entre guillemets

Lors du référencement d'une variable, il est généralement conseillé de placer son nom entre guillemets (""). Ceci empêche la réinterprétation de tous les caractères spéciaux à l'intérieur de la chaîne -- sauf pour $, ` (apostrophe inversée) et \ (échappement). [29] 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 d'une variable et son remplacement par sa valeur »).

On peut utiliser les guillemets pour empêcher les coupures de mots. [30] Un argument placé entre guillemets se présente comme un seul mot, même s'il contient des blancs.

Liste="un deux trois"

for a in $Liste    #  Divise la variable en plusieurs parties,
                   #+ utilise le blanc comme séparateur.
do
  echo "$a"
done
# un
# deux
# trois

echo "---"

for a in "$Liste"  # Préserve les blancs dans une unique 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 n'est nécessaire que lorsque la séparation des mots ou la préservation des blancs posent problème.

Exemple 5.1. Afficher des variables bizarres

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

var="'(]\\{}\$\""
echo $var        # '(]\{}$"
echo "$var"      # '(]\{}$"     Aucune différence.

echo

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

# Exemples ci-dessus fournis par Stéphane Chazelas.

exit 0

Les apostrophes (' ') fonctionnent un peu comme les guillemets mais ne permettent pas de référencer des variables, la signification spéciale de $ étant 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 (\) est interprété littéralement avec les apostrophes.

echo "Pourquoi n'est-il pas possible d'é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.


[28] 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).

[29]

Entourer le caractère « ! » de guillemets ("") provoque une erreur lorsque cette expression est utilisée en ligne de commande. Elle est alors interprétée comme une commande d'historique. À l'intérieur d'un script, le problème ne se pose pas car le mécanisme d'historique de Bash est désactivé.

Un problème plus ennuyeux est le comportement apparemment incohérent de \ à l'intérieur de guillemets (""), notamment après une commande echo -e.

bash$ echo bonjour\!
bonjour!
bash$ echo "bonjour\!"
bonjour\!

bash$ echo \
>
bash$ echo "\"
>
bash$ echo \a
a
bash$ echo "\a"
\a

bash$ echo x\ty
xty
bash$ echo "x\ty"
x\ty

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

Les guillemets doubles après un echo sont parfois un échappement pour \. De plus, l'option -e de echo a pour effet que « \t » est interprété en tab.

(Merci à Wayne Pollock pour nous l'avoir indiqué et à Geoff Lee et Daniel Barclay pour nous l'avoir expliqué.)

[30] Dans ce contexte, la « coupure de mots » signifie le fait de diviser la chaîne de caractères en un certain nombre d'arguments séparés.