Un bon moyen de travailler avec eval
est de le remplacer par echo
pour les tests. echo
et eval
travailler de la même manière (si nous mettons de côté l' \x
expansion effectuée par certaines echo
implémentations comme celle bash
de certaines dans certaines conditions).
Les deux commandes joignent leurs arguments avec un espace entre les deux. La différence est que le résultat est echo
affiché pendant qu'il eval
évalue / interprète le code shell comme résultat.
Donc, pour voir quel code shell
eval $(echo $var_name=$var_value)
évaluerait, vous pouvez exécuter:
$ echo $(echo $var_name=$var_value)
fruit=blue orange
Ce n'est pas ce que vous voulez, ce que vous voulez c'est:
fruit=$var_value
De plus, l'utilisation $(echo ...)
ici n'a pas de sens.
Pour afficher ce qui précède, vous devez exécuter:
$ echo "$var_name=\$var_value"
fruit=$var_value
Donc, pour l'interpréter, c'est simplement:
eval "$var_name=\$var_value"
Notez qu'il peut également être utilisé pour définir des éléments de tableau individuels:
var_name='myarray[23]'
var_value='something'
eval "$var_name=\$var_value"
Comme d'autres l'ont dit, si vous ne vous souciez pas que votre code soit bash
spécifique, vous pouvez l'utiliser declare
comme:
declare "$var_name=$var_value"
Notez cependant qu'il a des effets secondaires.
Il limite la portée de la variable à la fonction dans laquelle elle est exécutée. Vous ne pouvez donc pas l'utiliser par exemple dans des choses comme:
setvar() {
var_name=$1 var_value=$2
declare "$var_name=$var_value"
}
setvar foo bar
Parce que cela déclarerait une foo
variable locale à setvar
so serait inutile.
bash-4.2
ajouté une -g
option pour declare
déclarer une variable globale , mais ce n'est pas ce que nous voulons non plus car notre setvar
définirait une variable globale par opposition à celle de l'appelant si l'appelant était une fonction, comme dans:
setvar() {
var_name=$1 var_value=$2
declare -g "$var_name=$var_value"
}
foo() {
local myvar
setvar myvar 'some value'
echo "1: $myvar"
}
foo
echo "2: $myvar"
qui produirait:
1:
2: some value
Notez également que while declare
est appelé declare
(en fait bash
emprunté au concept du shell Korn typeset
), si la variable est déjà définie, declare
ne déclare pas de nouvelle variable et la façon dont l'affectation est effectuée dépend du type de la variable.
Par exemple:
varname=foo
varvalue='([PATH=1000]=something)'
declare "$varname=$varvalue"
produira un résultat différent (et aura potentiellement des effets secondaires désagréables) s'il a varname
été précédemment déclaré comme un scalaire , un tableau ou un tableau associatif .
eval
cette façon est faux. Vous développez$var_value
avant de le transmettre, ceeval
qui signifie qu'il va être interprété comme du code shell! (essayez par exemple avecvar_value="';:(){ :|:&};:'"
)