我曾经能够做这样的事情:
X=123 cat <<EOF
X is $X
EOF
甚至更简单:
X=123 echo $X
安装 bash 修复后,第一个似乎仍然可以在 Mac OS X 上运行,但是似乎都不再可以在 AWS 中的 Ubuntu 14.04 实例上运行。是什么使得它echo
不再cat
能够访问这些环境变量?更奇怪的是,当我将环境变量传递给 NodeJS 应用程序时,我似乎没有任何问题:
cat <<EOF > test.js
console.log('X is ' + process.env.X);
EOF
X=123 node test.js
这似乎也适用于 bash 脚本:
cat <<EOF > test.sh
echo X is \$X
EOF
chmod +x test.sh
X=123 ./test.sh
答案1
在任何 POSIX shell 中,当您编写
X=123 echo $X
the$X
在执行整个命令之前展开,即如果$X
最初未设置,您将得到:
X=123 echo
然后执行。您可以或多或少地看到 shell 正在做什么set -x
:
$ set -x
$ X=123 echo X=$X
+ X=123
+ echo X=
X=
$ set +x
您可以看到echo
(实际上是 shell 本身,它在执行之前进行扩展echo
)仍然可以访问环境:
$ X=123 eval 'echo $X'
123
的问题cat <<EOF
是类似的。请注意,关于bash
,旧版本(4.1之前)存在一个错误,在CHANGES
文件中描述为:
修复了导致此处文档中的变量扩展以在任何临时环境中查找的错误。
这可能是在 Mac OS X 下观察到的行为的原因。不要依赖此错误。
答案2
您对此处文档的问题可能与此无关。问题是,bash
将同时执行扩展和赋值 - 因此前导X=123...
不应影响从此处文档中扩展的值。这是因为此处文档是一个输入文件描述符,bash
必须在调用时构建并传递给它,cat
其方式与在传递该描述符及其环境的其余部分之前必须分配123
的方式相同。$X
cat
execve
考虑:
X=321; X=123 bash <<HEREDOC
echo "$X is not yet \$X and $$ is not yet \$$."
HEREDOC
输出
321 is not yet 123 and 17134 is not yet 17225.