在阅读了 Bash 手册页 和 这篇文章之后,我仍然无法理解 eval
命令的具体用途以及它的典型用途。
例如,如果我们这样做:
$ set -- one two three # Sets $1 $2 $3
$ echo $1
one
$ n=1
$ echo ${$n} ## First attempt to echo $1 using brackets fails
bash: ${$n}: bad substitution
$ echo $($n) ## Second attempt to echo $1 using parentheses fails
bash: 1: command not found
$ eval echo \${$n} ## Third attempt to echo $1 using 'eval' succeeds
one
这里到底发生了什么,美元符号和反斜杠如何与问题联系起来?
原文由 stratis 发布,翻译遵循 CC BY-SA 4.0 许可协议
eval
将字符串作为其参数,并对其进行评估,就好像您在命令行上键入了该字符串一样。 (如果你传递了几个参数,它们首先用它们之间的空格连接起来。)${$n}
是 bash 中的语法错误。在大括号内,你只能有一个变量名,带有一些可能的前缀和后缀,但你不能有任意的 bash 语法,特别是你不能使用变量扩展。不过,有一种说法是“名称在此变量中的变量的值”:$(…)
在子shell 中运行括号内指定的命令(即在从当前shell 继承所有设置(例如变量值)的单独进程中),并收集其输出。所以echo $($n)
运行$n
作为 shell 命令,并显示其输出。由于$n
计算结果为1
,$($n)
尝试运行命令1
不存在 81781641eval echo \${$n}
运行传递给eval
的参数。展开后参数为echo
和${1}
。所以eval echo \${$n}
运行命令echo ${1}
。请注意,大多数情况下,您必须在变量替换和命令替换周围使用双引号(即,只要有
$
):"$foo", "$(foo)"
。 总是在变量和命令替换周围加上双引号,除非你知道你需要把它们去掉。如果没有双引号,shell 会执行字段拆分(即,它将变量的值或命令的输出拆分为单独的单词),然后将每个单词视为通配符模式。例如:eval
不经常使用。在某些 shell 中,最常见的用途是获取名称直到运行时才知道的变量的值。在 bash 中,由于${!VAR}
语法,这不是必需的。eval
当您需要构造一个包含运算符、保留字等的较长命令时仍然很有用。