Хороший способ работы с ним 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
so, и было бы бесполезно.
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="';:(){ :|:&};:'"
)