Dobrym sposobem pracy eval
jest zastąpienie go echo
testem. echo
i eval
działają tak samo (jeśli odłożymy na bok \x
rozszerzenie wykonane przez niektóre echo
implementacje, takie jak bash
pod pewnymi warunkami).
Oba polecenia łączą argumenty z odstępem między nimi. Różnica polega na tym, że echo
wyświetla wynik, podczas gdy eval
ocenia / interpretuje jako kod powłoki wynik.
Tak więc, aby zobaczyć jaki kod powłoki
eval $(echo $var_name=$var_value)
oceni, możesz uruchomić:
$ echo $(echo $var_name=$var_value)
fruit=blue orange
Nie tego chcesz, czego chcesz:
fruit=$var_value
Również użycie $(echo ...)
tutaj nie ma sensu.
Aby wyświetlić powyższe, uruchomiłbyś:
$ echo "$var_name=\$var_value"
fruit=$var_value
Aby to zinterpretować, to po prostu:
eval "$var_name=\$var_value"
Zauważ, że można go również użyć do ustawienia poszczególnych elementów tablicy:
var_name='myarray[23]'
var_value='something'
eval "$var_name=\$var_value"
Jak powiedzieli inni, jeśli nie zależy ci na tym bash
, aby kod był konkretny, możesz użyć declare
jako:
declare "$var_name=$var_value"
Należy jednak pamiętać, że ma pewne skutki uboczne.
Ogranicza zakres zmiennej do funkcji, w której jest uruchamiana. Nie można jej więc używać na przykład do:
setvar() {
var_name=$1 var_value=$2
declare "$var_name=$var_value"
}
setvar foo bar
Ponieważ zadeklarowałoby to foo
lokalną zmienną, setvar
więc byłoby to bezużyteczne.
bash-4.2
dodaliśmy -g
opcję declare
deklarowania zmiennej globalnej , ale nie tego też chcemy, ponieważ setvar
ustawilibyśmy zmienną globalną w przeciwieństwie do zmiennej wywołującej, gdyby funkcja wywołująca była jak w:
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"
co dałoby wynik:
1:
2: some value
Zauważ też, że chociaż declare
jest wywoływany declare
(faktycznie bash
pożyczył koncepcję z typeset
wbudowanej powłoki Korna ), jeśli zmienna jest już ustawiona, declare
nie deklaruje nowej zmiennej, a sposób wykonania przypisania zależy od typu zmiennej.
Na przykład:
varname=foo
varvalue='([PATH=1000]=something)'
declare "$varname=$varvalue"
spowoduje inny wynik (i może mieć nieprzyjemne skutki uboczne), jeśli varname
został wcześniej zadeklarowany jako skalar , tablica lub tablica asocjacyjna .
eval
ten sposób jest złe. Rozwijasz się$var_value
przed przekazaniem go,eval
co oznacza, że będzie interpretowany jako kod powłoki! (spróbuj na przykład zvar_value="';:(){ :|:&};:'"
)