Хороший способ работы с ним 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переменную, локальную для setvarso, и было бы бесполезно.
bash-4.2добавлена -gопция для declareобъявить глобальную переменную, но это не то , что мы хотим , или как наши setvarбы установить глобальный вар в противоположность тому , что вызывающего абонента , если вызывающий абонент является функцией, как в:
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встроенной оболочки Korn ), если переменная уже установлена,declare не объявляет новую переменную, и способ ее назначения зависит от типа переменной.
Например:
varname=foo
varvalue='([PATH=1000]=something)'
declare "$varname=$varvalue"
приведет к другому результату (и потенциально может иметь неприятные побочные эффекты), если он varnameбыл ранее объявлен как скаляр , массив или ассоциативный массив .
evalэтот путь неправильно. Вы расширяете,$var_valueпрежде чем передать его,evalчто означает, что он будет интерпретироваться как шелл-код! (попробуйте, например, сvar_value="';:(){ :|:&};:'")