我曾經能夠做這樣的事情:
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.