BASH_SUBSHELL 實現於 Bash 3.0,我一直想不到它在實際編碼中有什麼用,後來在 Bash 的 Change Log 裏找到一句話,才知道它是做調試用的:html
New variables to support the bash debugger: BASH_ARGC, BASH_ARGV,
BASH_SOURCE, BASH_LINENO, BASH_SUBSHELL, BASH_EXECUTION_STRING,
BASH_COMMANDshell
BASH_SUBSHELL 是 subshell 嵌套層次的累加器,那麼按理說,全部的 subshell 裏這個變量都應該加 1。那 Bash 的哪些語法是在 subshell 裏執行的呢?下面列舉一下:bash
那麼當 BASH_SUBSHELL 出如今這些語法中時,它的值就應該加 1,對不對?然而實際狀況卻不是這樣的,在我寫這篇文章時,Bash 的最新穩定版是 4.3.30,在該版本中,BASH_SUBSHELL 只會在上面列出的 1 和 2 兩種語法裏生效:編碼
$ (echo $BASH_SUBSHELL)debug 1調試 $ echo `echo $BASH_SUBSHELL`htm 1進程 $ echo $(echo $BASH_SUBSHELL)get 1編譯 |
在後三種語法裏不生效:
$ cat <(echo $BASH_SUBSHELL) 0 $ echo $BASH_SUBSHELL | cat 0 $ echo $BASH_SUBSHELL & [1] 91155 $ 0 |
搜索了一翻,在 help-bash 上發現已經有人提了個 bug,不過他僅僅提到了進程替換和命令替換中 BASH_SUBSHELL 表現不一致的事,Bash 做者也回覆說會在 Bash 下個版本也就是是 4.4 裏修復。而後我下了 4.4 alpha 版編譯以後發現,進程替換中 BASH_SUBSHELL 是生效了,但在管道和後臺命令中仍沒效果,因而我又頂起了這個郵件,詢問 Bash 做者是否能一塊兒修復,他的回覆是,後臺命令那個他會修的,但管道命令那個不許備修復。而後我就沒再追問爲何了,應該是實現上有困難,畢竟這是 Bash 私有的東西,做者有權決定該不應修。總之,我想說的是,在將來 Bash 4.4 發佈的時候,BASH_SUBSHELL 在除了管道以外的其餘子 Shell 裏,都應該能生效了。
此外,當我問這個問題的時候,有人回覆說,之因此 BASH_SUBSHELL 爲 0,是由於它是在父 Shell 裏展開以後才傳入子 Shell 的,也就是說,echo $BASH_SUBSHELL | cat 在傳入子 Shell 的時候就已經成了 echo 0 | cat,但這是不對的,咱們能夠舉一個反例,若是真是那樣的話,echo $BASHPID | cat 應該和 echo $BASHPID 的輸出同樣,但實際倒是不同的。因此能夠總結一下就是,歷來都不存在「在父 Shell 中展開變量,在子 Shell 裏執行展開後的命令」 這一回事,全部的變量都是在子 Shell 中展開而後執行的。