我曾经能够做这样的事情:
X=123 cat <<EOF
X is $X
EOF
Run Code Online (Sandbox Code Playgroud)
甚至更简单:
X=123 echo $X
Run Code Online (Sandbox Code Playgroud)
安装 bash 修复程序后,第一个似乎仍然可以在 Mac OS X 上运行,但是它们似乎都不再适用于我在 AWS 中的 Ubuntu 14.04 实例。是什么让它echo或cat不再可以访问这些环境变量?更奇怪的是,当我将 env vars 传递给 NodeJS 应用程序时,我似乎没有任何问题:
cat <<EOF > test.js
console.log('X is ' + process.env.X);
EOF
X=123 node test.js
Run Code Online (Sandbox Code Playgroud)
这似乎也适用于 bash 脚本:
cat <<EOF > test.sh
echo X is \$X
EOF
chmod +x test.sh
X=123 ./test.sh
Run Code Online (Sandbox Code Playgroud)
在任何 POSIX shell 中,当您编写
X=123 echo $X
Run Code Online (Sandbox Code Playgroud)
在$X整个命令执行之前展开,即如果$X最初未设置,您将得到:
X=123 echo
Run Code Online (Sandbox Code Playgroud)
然后执行。您可以或多或少地看到 shell 正在做什么set -x:
$ set -x
$ X=123 echo X=$X
+ X=123
+ echo X=
X=
$ set +x
Run Code Online (Sandbox Code Playgroud)
您可以看到echo(实际上是 shell 本身,在执行之前进行扩展echo)仍然可以访问环境:
$ X=123 eval 'echo $X'
123
Run Code Online (Sandbox Code Playgroud)
的问题cat <<EOF是类似的。请注意,关于bash,旧版本(4.1 之前)存在一个错误,在CHANGES文件中描述为:
修复了导致此处文档中的变量扩展以在任何临时环境中查看的错误。
这可能是在 Mac OS X 下观察到的行为的原因。不要依赖此错误。
您关于此处文档的问题可能与此无关。问题是,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
Run Code Online (Sandbox Code Playgroud)
321 is not yet 123 and 17134 is not yet 17225.
Run Code Online (Sandbox Code Playgroud)