Référencer des variables dans un script shell

10

Dans un script shell, si je définis une variable telle que FOO=25, y a-t-il une différence entre le référencer comme $FOO$et ${FOO}$?

Karnivaurus
la source
2
Vous ne devez pas utiliser le $à la fin! Il sera traité comme un caractère normal et non comme faisant partie du nom de la variable.
Byte Commander

Réponses:

16

Dans la plupart des situations à la fois $varet ${var}sont les mêmes. (Notez que vous ne devez pas utiliser un $à la fin!)

Un exemple où vous avez besoin d'accolades est lorsque vous devez placer une variable dans une chaîne continue.

Exemple:

var=hel
echo ${var}lo

sortira hello.

Aizuddin Zali
la source
11

Pour répondre à votre question principale, ${foo}est appelé "expansion des paramètres" . Pour être précis, le $paramètre lui - même démarre l'expansion des paramètres, ils { }sont en fait facultatifs selon la spécification POSIX , mais peuvent être utiles pour indiquer la fin du nom de la variable:

$ foo="bar"
$ echo $fooBaz   ## fails, no variable named $fooBaz exists

$ echo ${foo}Baz ## works, $foo is expanded and the string Baz is appended
barBaz

Fondamentalement, $fooet ${foo}sont identiques. Hormis les cas comme ci-dessus ou lorsque vous faites de la manipulation de chaînes , ils sont complètement équivalents.

Cependant, vous ne devriez pas vraiment utiliser l'un ou l'autre. La règle générale est que, à quelques exceptions près, vous devez toujours utiliser "$foo"ou "${foo}"et jamais $fooou ${foo}. Vous devez toujours citer vos variables pour éviter d'appeler l'opérateur split + glob (plus de détails plus loin). Vous ne voulez certainement pas $foo$. La finale $n'est pas pertinente:

$ foo="bar"
$ echo "$foo$"
bar$

Ainsi, alors que les variables non cotées sont parfois OK:

$ echo $foo
bar

Ils ne le sont généralement pas et devraient vraiment être évités:

$ if [ -n $foo ]; then echo empty; else echo "not empty"; fi ## fails
empty

$ if [ -n "$foo" ]; then echo empty; else echo "not empty"; fi ## works
not empty

Notez que les crochets ne sont pas utiles ici non plus:

$ if [ -n ${foo} ]; then echo empty; else echo "not empty"; fi  ## fails
empty

$ if [ -n "${foo}" ]; then echo empty; else echo "not empty"; fi ## works
not empty

Lorsque vous utilisez $fooou ${foo}, le shell divisera la valeur enregistrée dans la variable sur les espaces blancs (cela peut être modifié en définissant la IFSvariable sur autre chose) dans une liste, puis, chaque élément de la liste est traité comme un modèle global et développé en tous les fichiers ou répertoires correspondants. Il s'agit de l' opérateur split + glob . Pour illustrer, considérons un répertoire avec deux fichiers:

$ ls -l
-rw-r--r-- 1 terdon terdon 0 Oct  9 18:16 file1
-rw-r--r-- 1 terdon terdon 0 Oct  9 18:16 file2

Maintenant, définissons une variable sur foo *:

$ foo="foo *"

Que se passe-t-il si nous essayons de vérifier si un fichier portant ce nom existe?

$ if [ -e $foo ]; then echo "file exists"; else echo "no such file"; fi
file exists

La variable a été divisée en fooet *, comme il *s'agit d'un caractère générique qui correspond à n'importe quelle chaîne, le shell vous indique qu'un fichier appelé foo *exxists. Cependant, si nous le citons correctement, cela ne se produit pas:

$ if [ -e "$foo" ]; then echo "file exists"; else echo "no such file"; fi
no such file

C'était un exemple trivial pour illustrer ce point. Imaginez si j'avais utilisé rmau lieu de echobien.

Donc, première règle: citez toujours vos variables. Vous pouvez utiliser soit "$foo"ou, "${foo}"mais le citer de toute façon. Pour plus de détails sur l'utilisation des variables en toute sécurité, consultez ces articles:

terdon
la source
Je ne voulais pas modifier votre excellente réponse, mais ne devrait pas l' $ var="foo *"être $ foo="foo *"? Vous n'utilisez varnulle part.
Joe
@Joe oh, bonne douleur! Oui, bien sûr, merci, pour l'avoir signalé. N'hésitez pas à corriger de telles erreurs en suggérant une modification, soit dit en passant. Ce genre de chose est très encouragé, précisément pour éviter des erreurs idiotes comme celle-ci.
terdon