Uma boa maneira de trabalhar eval
é substituí-lo echo
pelos testes. echo
e eval
funciona da mesma forma (se deixarmos de lado a \x
expansão feita por algumas echo
implementações como bash
as de algumas condições).
Ambos os comandos juntam seus argumentos com um espaço no meio. A diferença é que echo
exibe o resultado enquanto eval
avalia / interpreta como código shell o resultado.
Então, para ver qual código shell
eval $(echo $var_name=$var_value)
avaliar, você pode executar:
$ echo $(echo $var_name=$var_value)
fruit=blue orange
Não é isso que você quer, o que você quer é:
fruit=$var_value
Além disso, usar $(echo ...)
aqui não faz sentido.
Para gerar o resultado acima, você executaria:
$ echo "$var_name=\$var_value"
fruit=$var_value
Então, para interpretar, é simplesmente:
eval "$var_name=\$var_value"
Observe que também pode ser usado para definir elementos individuais da matriz:
var_name='myarray[23]'
var_value='something'
eval "$var_name=\$var_value"
Como outros já disseram, se você não se importa que seu código seja bash
específico, você pode usar declare
como:
declare "$var_name=$var_value"
No entanto, note que ele tem alguns efeitos colaterais.
Limita o escopo da variável à função em que ela é executada. Portanto, você não pode usá-la, por exemplo, em coisas como:
setvar() {
var_name=$1 var_value=$2
declare "$var_name=$var_value"
}
setvar foo bar
Porque isso declararia uma foo
variável local para setvar
isso seria inútil.
bash-4.2
adicionou uma -g
opção para declare
declarar uma variável global , mas isso não é o que queremos, pois o nosso setvar
definiria uma var global em oposição à do chamador se o chamador fosse uma função, como em:
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 produziria:
1:
2: some value
Além disso, observe que while declare
é chamado declare
(na verdade, bash
o conceito emprestado do shell Korn typeset
), se a variável já estiver definida, declare
não declara uma nova variável e a maneira como a atribuição é feita depende do tipo da variável.
Por exemplo:
varname=foo
varvalue='([PATH=1000]=something)'
declare "$varname=$varvalue"
produzirá um resultado diferente (e potencialmente terá efeitos colaterais desagradáveis) se tiver varname
sido declarado anteriormente como escalar , matriz ou matriz associativa .
eval
esse caminho está errado. Você está expandindo$var_value
antes de passá-lo para oeval
que significa que ele será interpretado como código do shell! (tente por exemplo comvar_value="';:(){ :|:&};:'"
)