Bash Shell 指令碼/管道和替換
正如我們所見,一個命令的返回值,嚴格來說,只是一個小的非負整數,用於表示成功或失敗。它真正的輸出是它寫入標準輸出流的內容。預設情況下,寫入標準輸出流的文字會列印到終端,但有一些方法可以“捕獲”它並用作命令的真實返回值。
當一系列命令在管道中連結在一起時,每個命令的輸出都會作為輸入傳遞給下一個命令。這是一種非常強大的技術,因為它允許我們將許多小的實用程式組合起來,創造出複雜的功能。
命令替換有點像變數擴充套件,但它執行一個命令並捕獲它的輸出,而不是簡單地檢索變數的值。例如,考慮我們上面的 `get_password` 示例。
#!/bin/bash
function get_password ( )
# Usage: get_password VARNAME
# Asks the user for a password; saves it as $VARNAME.
# Returns a non-zero exit status if standard input is not a terminal, or if the
# "read" command returns a non-zero exit status.
{
if [[ -t 0 ]] ; then
read -r -p 'Password:' -s "$1" && echo
else
return 1
fi
}
get_password PASSWORD && echo "$PASSWORD"
實際上,呼叫者沒有必要將密碼儲存在變數中。如果 `get_password` 只將密碼列印到它的標準輸出,那麼呼叫者可以使用命令替換,並直接使用它。
#!/bin/bash
function get_password ( )
# Usage: get_password
# Asks the user for a password; prints it for capture by calling code.
# Returns a non-zero exit status if standard input is not a terminal, or if
# standard output *is* a terminal, or if the "read" command returns a non-zero
# exit status.
{
if [[ -t 0 ]] && ! [[ -t 1 ]] ; then
local PASSWORD
read -r -p 'Password:' -s PASSWORD && echo >&2
echo "$PASSWORD"
else
return 1
fi
}
echo "$(get_password)"
為了評估 `"$(get_password)"`,Bash 在一個子 shell 中執行命令 `get_password`,捕獲它的標準輸出,並將 `"$(get_password)"` 替換為捕獲的輸出。
除了 `"$(…)"` 語法之外,還支援一種更古老的語法 `…`(使用反引號),並且仍然很常見。這兩種語法具有相同的效果,但 `…` 的語法更嚴格,在複雜的情況下,它可能更難正確使用。
命令替換允許巢狀;類似於 `"$(b "$(c)")"` 的內容是允許的。(它執行命令 `c`,使用它的輸出作為 `b` 的引數,並使用那個的輸出作為 `a` 的引數)。
命令替換實際上可以包含一系列命令,而不僅僅是一個命令。正如我們之前所見,分號可以用作換行符來分隔命令,這在命令替換中很常見。每個用分號分隔的語句都在單個子 shell 中依次執行,並且它們的組合輸出被捕獲。命令替換還可以包含變數賦值和函式定義,但這些只有在替換內部有用,並且在替換完成後不會保留在父 shell 中。