一个很好的工作方式eval
是将其替换echo
为测试。echo
并eval
以相同的方式工作(如果我们在某些情况下不考虑\x
通过的echo
实现来扩展bash
)。
这两个命令的参数之间都用一个空格隔开。区别在于echo
显示结果同时将结果eval
评估 / 解释为shell代码。
那么,看一下什么shell代码
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
是从Korn shell的typeset
内置函数中借用的概念),但是如果已经设置了变量,declare
则不会声明新变量,并且赋值的方式取决于变量的类型。
例如:
varname=foo
varvalue='([PATH=1000]=something)'
declare "$varname=$varvalue"
如果varname
先前被声明为标量,数组或关联数组,则将产生不同的结果(并可能有讨厌的副作用)。
eval
这种方式是错误的。您$var_value
在将其传递给eval
它之前先进行扩展,这意味着它将被解释为shell代码!(尝试例如用var_value="';:(){ :|:&};:'"
)