为何变量未应用于后续命令的运行环境?
问题分析与解决
你执行的命令:
z=bye z=hello echo $z echo $z
预期输出:
hello bye
实际输出:
bye bye
错误原因
问题出在bash对简单命令的执行顺序上,按照bash手册的规则:
- 先标记并保存命令名前的变量赋值(这里就是
z=hello),留到后面处理; - 对非赋值/重定向的内容(这里是
echo $z)先做展开——这时候$z会用当前shell环境里的旧值bye来替换,所以echo的参数已经确定是bye了; - 之后才会把
z=hello添加到echo命令的执行环境中,但这时候echo已经拿到了展开后的参数,不会再重新读取新的z值; - 最后
echo执行,输出的是之前展开好的bye。
手册里提到的“变量会被添加至被执行命令的环境中,且不会影响当前shell环境”是正确的——当前shell的z确实还是bye,但你预期的echo能用到新z值的前提是,$z的展开要在新环境里发生,而不是当前shell环境。
正确写法
如果想让echo使用z=hello这个值,需要让$z的展开在新环境中进行,有两种常见方式:
- 使用子shell,让赋值和echo在同一个子shell环境里执行:
z=bye (z=hello; echo $z) echo $z
- 通过
bash -c让命令在新的shell进程中执行,此时变量展开会在新环境里完成:
z=bye z=hello bash -c 'echo $z' echo $z
这两种写法的输出都会符合你的预期:
hello bye
内容的提问来源于stack exchange,提问作者Adrian
相关产品推荐
相关产品推荐

