Bash

通過 bash 評估與管道

  • May 9, 2018

使用有什麼區別:

eval 'echo "foo"'

echo 'echo "foo"' | bash

有沒有?

簡答

執行的命令eval在目前 shell 中執行,通過管道傳輸的命令bash在子 shell 中執行,例如:

> echo 'x=42' | bash; echo $x

> eval 'x=42'; echo $x
42

更長的答案

在評論中聲稱,在bash(>=4.2) 的更新版本中,第一個命令也可能具有相同的效果。然而,情況似乎並非如此。

實際上有幾個因素會導致管道命令不在目前會話中執行:管道和bash命令。

在大多數情況下,管道命令在子 shell 中執行。Bash 手冊(第 3.2.2 節:管道)有以下說法:

管道中的每個命令都在其自己的子 shell 中執行(請參閱命令執行環境)。

正如評論中所指出的,可以通過lastpipe選項修改此行為。Bash 手冊(第 4.3.2 節:The Shopt Builtin)對lastpipe選項有以下說明:

最後一個管道

如果設置,並且作業控制未啟動,則 shell 將在目前 shell 環境中執行未在後台執行的管道的最後一個命令。

我們可以驗證如下。

首先啟用lastpipe

> shopt -s lastpipe

然後禁用作業控制:

> set +m

現在執行一個從管道中設置變數的命令:

> unset x
> echo x=42 | while IFS= read -r line; do eval "${line}"; done;
> echo $x
42

請注意,我們使用while循環和read命令作為解決方法,因為eval命令無法從標準輸入讀取其輸入(因此無法從管道獲取其輸入)。

這個例子展示了管道中最右邊的命令實際上可以在目前 shell 中執行。然而,這實際上並不影響我們原來的例子。即使lastpipe啟用和禁用作業控制,當管道到時我們仍然得到以下結果bash

> echo 'x=42' | bash; echo $x

>

這是因為bash命令本身在子 shell 中執行其輸入。

引用自:https://unix.stackexchange.com/questions/442215