Хороший спосіб роботи eval
- це замінити його echo
на тестування. echo
і eval
працювати так само (якщо ми відкладемо \x
розширення, здійснене деякими echo
реалізаціями, такими як bash
's за певних умов).
Обидві команди з'єднують свої аргументи з одним проміжком між ними. Різниця полягає в тому, що echo
відображає результат, тоді як eval
оцінює / інтерпретує як оболонку коду результату.
Отже, щоб побачити, який код оболонки
eval $(echo $var_name=$var_value)
Ви можете оцінити, ви можете запустити:
$ echo $(echo $var_name=$var_value)
fruit=blue orange
Це не те, що ти хочеш, а те, що ти хочеш:
fruit=$var_value
Також використовувати $(echo ...)
тут не має сенсу.
Щоб вивести вищезазначене, слід виконати:
$ echo "$var_name=\$var_value"
fruit=$var_value
Отже, для його тлумачення це просто:
eval "$var_name=\$var_value"
Зауважте, що він також може бути використаний для встановлення окремих елементів масиву:
var_name='myarray[23]'
var_value='something'
eval "$var_name=\$var_value"
Як говорили інші, якщо вам не важливо, щоб ваш код був bash
конкретним, ви можете використовувати declare
як:
declare "$var_name=$var_value"
Однак зауважте, що він має деякі побічні ефекти.
Це обмежує область змінної функцією, в якій вона запущена. Отже, ви не можете використовувати її, наприклад, у таких речах, як:
setvar() {
var_name=$1 var_value=$2
declare "$var_name=$var_value"
}
setvar foo bar
Тому що це оголошує foo
мінливу локальну на setvar
так було б марним.
bash-4.2
додано -g
параметр для declare
оголошення глобальної змінної, але це не те, чого ми хочемо, так як наш setvar
встановив би глобальний var на відміну від виклику, якщо викликає функцію, як у:
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"
який виведе:
1:
2: some value
Також зауважте, що в той час, declare
як викликається declare
(фактично bash
запозичена концепція з typeset
вбудованої оболонки Корна ), якщо змінна вже встановлена, declare
не оголошує нову змінну, і спосіб виконання призначення залежить від типу змінної.
Наприклад:
varname=foo
varvalue='([PATH=1000]=something)'
declare "$varname=$varvalue"
призведе до іншого результату (і, можливо, матиме неприємні побічні ефекти), якщо varname
раніше він був оголошений як скалярний , масив або асоціативний масив .
eval
цей спосіб неправильно. Ви розширюєтесь,$var_value
перш ніж передавати його,eval
а значить, він буде інтерпретуватися як код оболонки! (спробуйте, наприклад, зvar_value="';:(){ :|:&};:'"
)