Un buon modo di lavorare evalè sostituirlo con echoper i test. echoe evalfunzionano allo stesso modo (se mettiamo da parte l' \xespansione effettuata da alcune echoimplementazioni come quelle bashin 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 bashspecifico, puoi usare declarecome:
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 setvarcosì sarebbe inutile.
bash-4.2aggiunta -gun'opzione per declaredichiarare una variabile globale , ma non è nemmeno quello che vogliamo, dato setvarche 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 declareviene chiamato declare(in realtà bashpreso in prestito il concetto dalla shell di Korntypeset ), se la variabile è già impostata, declarenon 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 è varnamestato precedentemente dichiarato come array scalare , array o associativo .
evalquel modo è sbagliato. Ti stai espandendo$var_valueprima di passarlo alevalche significa che verrà interpretato come codice shell! (prova ad esempio convar_value="';:(){ :|:&};:'")