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?
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:
${array[42]}
${filename%.*}
(supprimer l'extension)"$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.
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!
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
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.
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.
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"
# 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)
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é.
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: