Una buena forma de trabajar eval
es reemplazarlo por echo
para probar. echo
y eval
funciona igual (si dejamos de lado la \x
expansión realizada por algunas echo
implementaciones como bash
en algunas condiciones).
Ambos comandos unen sus argumentos con un espacio en el medio. La diferencia es que echo
muestra el resultado mientras eval
evalúa / interpreta como código shell el resultado.
Entonces, para ver qué código de shell
eval $(echo $var_name=$var_value)
evaluaría, puede ejecutar:
$ echo $(echo $var_name=$var_value)
fruit=blue orange
Eso no es lo que quieres, lo que quieres es:
fruit=$var_value
Además, usar $(echo ...)
aquí no tiene sentido.
Para generar lo anterior, ejecutarías:
$ echo "$var_name=\$var_value"
fruit=$var_value
Entonces, para interpretarlo, eso es simplemente:
eval "$var_name=\$var_value"
Tenga en cuenta que también se puede usar para establecer elementos de matriz individuales:
var_name='myarray[23]'
var_value='something'
eval "$var_name=\$var_value"
Como otros han dicho, si no te importa que tu código sea bash
específico, puedes usarlo declare
como:
declare "$var_name=$var_value"
Sin embargo, tenga en cuenta que tiene algunos efectos secundarios.
Limita el alcance de la variable a la función donde se ejecuta. Por lo tanto, no puede usarla, por ejemplo, en cosas como:
setvar() {
var_name=$1 var_value=$2
declare "$var_name=$var_value"
}
setvar foo bar
Porque eso declararía que una foo
variable local setvar
sería inútil.
bash-4.2
agregó una -g
opción para declare
declarar una variable global , pero eso tampoco es lo que queremos, ya setvar
que estableceríamos una var global en lugar de la de la persona que llama si la persona que llama fue una función, como en:
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"
que daría salida:
1:
2: some value
Además, tenga en cuenta que mientras declare
se llama declare
(en realidad bash
tomó prestado el concepto de la construcción del shell Korn typeset
), si la variable ya está establecida, declare
no declara una nueva variable y la forma en que se realiza la asignación depende del tipo de la variable.
Por ejemplo:
varname=foo
varvalue='([PATH=1000]=something)'
declare "$varname=$varvalue"
producirá un resultado diferente (y potencialmente tendrá efectos secundarios desagradables) si varname
se declaró previamente como un escalar , matriz o matriz asociativa .
eval
ese camino está mal. ¡Se está expandiendo$var_value
antes de pasarlo, loeval
que significa que se interpretará como código shell! (prueba por ejemplo convar_value="';:(){ :|:&};:'"
)