eval用于重新解析并执行字符串命令,解决shell单次变量展开无法处理嵌套引用的问题,如动态命令构造、间接变量访问等,但存在安全风险,应优先使用${!var}等更安全替代方案。

eval 在 Shell 脚本中用于**重新解析并执行一段字符串作为命令**,特别适合处理“变量中还包含变量引用”的场景——也就是需要二次展开的情况。
为什么普通变量展开不够用?
Shell 默认只做一次变量展开。比如:
name="world" msg="Hello \$name" echo $msg # 输出:Hello $name($name 没被替换)
这里 $msg 里存的是字面量 Hello $name,Shell 不会自动再把里面的 $name 展开。这时候就需要 eval 来触发第二次解析。
基本用法:让嵌套变量生效
用 eval 执行带变量引用的字符串:
- 确保字符串中变量引用写法正确(如
"\$var"或'$var',避免过早展开) - 用双引号包裹整个
eval参数,保持空格和结构 - 执行后,内部变量会被当前 Shell 环境解析
示例:
name="Linux" template='echo "Welcome to \$name!"' eval "$template" # 输出:Welcome to Linux!
常见实用场景
动态构造并执行命令:
比如根据配置生成服务启动命令:
service="nginx" action="start" cmd="systemctl \$action \$service" eval "$cmd" # 相当于运行:systemctl start nginx
间接引用变量名(类似“变量的变量”):
host1="192.168.1.10"
host2="192.168.1.11"
node="host1"
eval "ip=\${$node}" # ip 变成 192.168.1.10
echo $ip
注意:${$node} 写法在 eval 中才合法;直接写 ${host1} 是常规展开,而 ${$node} 是让 eval 把 $node 先展开成 host1,再取其值。
安全与替代建议
eval 强大但危险:若字符串含用户输入或不可信内容,可能引发命令注入。
- 优先考虑用间接引用(
${!var})代替简单变量间接访问:node=host1; echo ${!node} - 避免拼接未过滤的输入,例如:
user_input="; rm -rf /"; eval "echo hello \$user_input"会执行删除 - 调试时可用
echo先打印将要执行的命令:echo "$cmd"; eval "$cmd"
真正需要动态解析逻辑、且输入可控时,eval 才是合理选择。











