web-dev-qa-db-fra.com

Quand avons-nous besoin d'accolades autour des variables Shell?

Dans les scripts Shell, quand utilisons-nous {} lors du développement de variables?

Par exemple, j'ai vu ce qui suit:

var=10        # Declare variable

echo "${var}" # One use of the variable
echo "$var"   # Another use of the variable

Y a-t-il une différence significative, ou est-ce juste du style? L'un est-il préféré à l'autre?

577
New User

Dans cet exemple particulier, cela ne fait aucune différence. Cependant, les {} dans ${} sont utiles si vous souhaitez développer la variable foo dans la chaîne.

"${foo}bar"

puisque "$foobar" élargirait la variable identifiée par foobar.

Les accolades sont également obligatoires sans condition lorsque:

  • développer des éléments de tableau, comme dans ${array[42]}
  • en utilisant des opérations de développement de paramètres, comme dans ${filename%.*} (supprimer l'extension)
  • extension des paramètres de position au-delà de 9: "$8 $9 ${10} ${11}"

Faire cela partout, au lieu de simplement dans des cas potentiellement ambigus, peut être considéré comme une bonne pratique de programmation. C’est à la fois pour la cohérence et pour éviter des surprises comme $foo_$bar.jpg, où il n’est pas évident que le trait de soulignement fasse partie du nom de la variable.

666
Fred Foo

Les variables sont déclarées et attribuées sans $ et sans {}. Vous devez utiliser

var=10

assigner. Pour lire à partir de la variable (autrement dit, "développer" la variable), vous devez utiliser $.

$var      # use the variable
${var}    # same as above
${var}bar # expand var, and append "bar" too
$varbar   # same as ${varbar}, i.e expand a variable called varbar, if it exists.

Cela m'a parfois confondu - dans d'autres langues, nous nous référons à la variable de la même manière, que ce soit à gauche ou à droite d'une affectation. Mais Shell-scripting est différent, $var=10 ne fait pas ce que vous pourriez penser!

117
Aaron McDaid

Vous utilisez {} pour le regroupement. Les accolades sont nécessaires pour déréférencer les éléments du tableau. Exemple:

dir=(*)           # store the contents of the directory into an array
echo "${dir[0]}"  # get the first entry.
echo "$dir[0]"    # incorrect
30
glenn jackman

Vous pouvez également manipuler du texte entre les accolades:

STRING="./folder/subfolder/file.txt"
echo ${STRING} ${STRING%/*/*}

Résultat:

./folder/subfolder/file.txt ./folder

ou

STRING="This is a string"
echo ${STRING// /_}

Résultat:

This_is_a_string

Vous avez raison de dire que les "variables normales" ne sont pas nécessaires ... Mais c'est plus utile pour le débogage et la lecture d'un script.

26
SierraX

La fin du nom de la variable est généralement indiquée par un espace ou une nouvelle ligne. Mais que se passe-t-il si nous ne voulons pas d'espace ou de saut de ligne après avoir imprimé la valeur de la variable? Les accolades indiquent à l'interpréteur de shell où se trouve la fin du nom de la variable.

Exemple classique 1) - Variable shell sans espaces de fin

TIME=10

# WRONG: no such variable called 'TIMEsecs'
echo "Time taken = $TIMEsecs"

# What we want is $TIME followed by "secs" with no whitespace between the two.
echo "Time taken = ${TIME}secs"

Exemple 2) Java chemin de classe avec des jars versionnés

# WRONG - no such variable LATESTVERSION_src
CLASSPATH=hibernate-$LATESTVERSION_src.Zip:hibernate_$LATEST_VERSION.jar

# RIGHT
CLASSPATH=hibernate-${LATESTVERSION}_src.Zip:hibernate_$LATEST_VERSION.jar

(La réponse de Fred l'indique déjà, mais son exemple est un peu trop abstrait)

11
Sridhar Sarnobat

Suivant les suggestions de SierraX et Peter concernant la manipulation de texte, les accolades {} sont utilisées pour transmettre une variable à une commande, par exemple:

Supposons que vous avez un fichier sposi.txt contenant la première ligne d'un roman italien bien connu:

> sposi="somewhere/myfolder/sposi.txt"
> cat $sposi

Ouput: quel ramo del lago di como che volge a mezzogiorno

Maintenant, créez deux variables:

# Search the 2nd Word found in the file that "sposi" variable points to
> Word=$(cat $sposi | cut -d " " -f 2)

# This variable will replace the Word
> new_Word="filone"

Remplacez maintenant le contenu de la variable Word par celui de new_Word, dans le fichier sposi.txt

> sed -i "s/${Word}/${new_Word}/g" $sposi
> cat $sposi

Ouput: quel filone del lago di como che volge a mezzogiorno

Le mot "ramo" a été remplacé.

2
Fabio Natalini

Des accolades sont toujours nécessaires pour accéder aux éléments du tableau et réaliser leur développement.

Il est bon de ne pas faire preuve de trop de prudence et d'utiliser {} pour développer les variables du shell, même en l'absence d'ambiguïté.

Par exemple:

dir=log
prog=foo
path=/var/${dir}/${prog}      # excessive use of {}, not needed since / can't be a part of a Shell variable name
logfile=${path}/${prog}.log   # same as above, . can't be a part of a Shell variable name
path_copy=${path}             # {} is totally unnecessary
archive=${logfile}_Arch       # {} is needed since _ can be a part of Shell variable name

Donc, il vaut mieux écrire les trois lignes comme suit:

path=/var/$dir/$prog
logfile=$path/$prog.log
path_copy=$path

ce qui est nettement plus lisible.

Comme un nom de variable ne peut pas commencer par un chiffre, Shell n'a pas besoin de {} autour des variables numérotées (telles que $1, $2 etc.) à moins qu'un tel développement ne soit suivi d'un chiffre. C'est trop subtil et cela oblige à utiliser explicitement {} dans de tels contextes:

set app      # set $1 to app
fruit=$1le   # sets fruit to Apple, but confusing
fruit=${1}le # sets fruit to Apple, makes the intention clear

Voir:

1
codeforester