在上文中曾說到:html
本文中繼續深刻講三點:shell
若是有兩個同名的環境變量,很簡單,那麼後面的值會覆蓋前面的:數組
$ env foo=1 foo=2 bash -c 'echo $foo'bash 2函數 |
上篇文章中咱們沒有提到過函數,Bash 實際上是能夠從環境變量中導入函數的,好比下面這樣:htm
$ foo() { echo foo函數; }blog $ export -f foo繼承 $ bash字符串 $ fooget foo函數 |
上一級的 Shell 把函數傳給了它的 child shell,Bash 是怎麼實現的呢?咱們用 env 命令演示一下:
$ env 'BASH_FUNC_foo%%=() { echo foo函數; }' bash -c 'foo' foo函數 |
其實 Bash 就是把知足 "BASH_FUNC_函數名%%=(){ 函數體" 格式的環境變量做爲函數源碼解析並導入。因此兩個同名的變量和函數並不會衝突,能夠同時導入,像這樣:
$ env 'foo=1' 'BASH_FUNC_foo%%=() { echo $1; }' bash -c 'foo $foo' 1 |
既然能夠同時導入,那麼導出更沒問題了:
$ foo=1 $ foo(){ echo foo函數; } $ export foo;export -f foo $ env ... foo=1 BASH_FUNC_foo%%=() { echo foo函數 } ... |
注意,本文所講的表現僅適用於 Bash 4.3.30 及以後的版本,以前的 Bash 版本在導出函數時不會給函數名加上 BASH_FUNC_ 前綴和 %% 後綴,在導入時也不會識別前綴後綴,只要看到 = 右邊是 "() {" 這四個字符,就按函數導入,像這樣:
$ env 'foo=() { echo foo函數; }' bash -c 'foo' foo函數 |
因爲環境變量字符串的轉換和識別規則不一樣,假如你在 Bash 4.3.30 中打開一個 Bash 3.2.25,後者是沒法繼承到前者導出的函數的:
$ bash4.3.30 $ foo() { echo foo函數 ; } $ export -f foo $ bash3.2.25 $ foo bash3.2.25: foo: command not found |
反之亦然,同時 foo 會被導入成一個變量:
$ bash3.2.25 $ foo() { echo foo函數 ; } $ export -f foo $ bash4.3.30 $ foo bash3.2.25: foo: command not found $ echo $foo () { echo foo函數 } |