我偶然发现了这个:归结为示例
/ # a=$(eval echo hello world)
/ # echo $a
hello world
/ # $(eval echo hello world)
/bin/sh: hello: not found
/ # a=$(hello world)
/bin/sh: hello: not found
我希望第一行扩展到hello world
括号内,然后以与最后一行相同的方式扩展:a=$(hello world)
. 毕竟help eval
告诉我们:
将 ARG 组合成一个字符串,将结果用作 shell 的输入,然后执行结果命令。
如果 eval 确实在扩展$()
发生之前执行了结果命令——我期望——结果应该是一个错误,因为hello world
is not executable(除非有一个实际的hello
命令)
为什么没有 a=$(eval echo hello world)
按预期出错?
这不是替代的工作方式。仅仅存在
$(..)
就是导致eval
运行的原因首先, bash 中的
$(..)
命令替换是一种捕获在括号内运行的命令的输出并将其存储在变量中的方法。被其中$(..)
存在的内容的输出替换该部分
a=$(eval echo hello world)
由 shell 按以下顺序执行。eval echo hello world
执行简单,因为它运行 echo 命令并输出存储到变量中echo hello world
的字符串。hello world
a
该部分将按照 1) 中的说明
$(eval echo hello world)
返回。hello world
但是没有任何任务可以捕获$(..)
任何地方的输出。所以一个文字字符串被返回到 shell 即hello world
. shell 尝试将其解释为命令(文字hello
字符串)。因此,您看到的错误是找不到名称的命令同样的情况
a=$(hello world)
也发生。如 1) 中所述,该部分$(..)
将括号内的内容作为命令运行。因此,再次评估文字字符串会导致相同的错误。在情况 2) 和 3) 中,当
$(..)
展开 时,文字未加引号的字符串hello world
被返回到外壳,外壳受到分词的影响hello
,并world
作为两个单独的词。这就是为什么您遇到hello
作为命令而不是整个字符串运行的错误的原因hello world
。与任何命令一起使用时要小心
eval
,就像 even 一样简单echo
。未正确调用时存在执行危险命令的风险。请参阅使用是否始终安全eval echo
?