Un buon modo di lavorare eval
è sostituirlo con echo
per i test. echo
e eval
funzionano allo stesso modo (se mettiamo da parte l' \x
espansione effettuata da alcune echo
implementazioni come quelle bash
in alcune condizioni).
Entrambi i comandi uniscono i loro argomenti con uno spazio in mezzo. La differenza è che echo
visualizza il risultato mentre eval
valuta / interpreta il risultato come codice shell.
Quindi, per vedere quale codice shell
eval $(echo $var_name=$var_value)
valutare, è possibile eseguire:
$ echo $(echo $var_name=$var_value)
fruit=blue orange
Non è quello che vuoi, quello che vuoi è:
fruit=$var_value
Inoltre, utilizzare $(echo ...)
qui non ha senso.
Per generare quanto sopra, dovresti eseguire:
$ echo "$var_name=\$var_value"
fruit=$var_value
Quindi, per interpretarlo, è semplicemente:
eval "$var_name=\$var_value"
Si noti che può anche essere utilizzato per impostare singoli elementi dell'array:
var_name='myarray[23]'
var_value='something'
eval "$var_name=\$var_value"
Come altri hanno già detto, se non ti interessa che il tuo codice sia bash
specifico, puoi usare declare
come:
declare "$var_name=$var_value"
Tuttavia nota che ha alcuni effetti collaterali.
Limita l'ambito della variabile alla funzione in cui è eseguita. Quindi non puoi usarla per esempio in cose come:
setvar() {
var_name=$1 var_value=$2
declare "$var_name=$var_value"
}
setvar foo bar
Perché ciò dichiarerebbe a foo
variabile locale setvar
così sarebbe inutile.
bash-4.2
aggiunta -g
un'opzione per declare
dichiarare una variabile globale , ma non è nemmeno quello che vogliamo, dato setvar
che imposteremmo una var globale rispetto a quella del chiamante se il chiamante fosse una funzione, come in:
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"
che produrrebbe:
1:
2: some value
Inoltre, nota che while declare
viene chiamato declare
(in realtà bash
preso in prestito il concetto dalla shell di Korntypeset
), se la variabile è già impostata, declare
non dichiara una nuova variabile e il modo in cui viene eseguita l'assegnazione dipende dal tipo di variabile.
Per esempio:
varname=foo
varvalue='([PATH=1000]=something)'
declare "$varname=$varvalue"
produrrà un risultato diverso (e potenzialmente avrà effetti collaterali negativi) se è varname
stato precedentemente dichiarato come array scalare , array o associativo .
eval
quel modo è sbagliato. Ti stai espandendo$var_value
prima di passarlo aleval
che significa che verrà interpretato come codice shell! (prova ad esempio convar_value="';:(){ :|:&};:'"
)