script Bash:使用'true`




ubuntu shell script if condition (4)

以下可能是等效的,更直接的:

if [ "${SOME_VAR+x}" ] then
    ...
fi

或者,在作業案例中:

[ "${SOME_VAR+x}" ] || SOME_VAR="..."

如果未設置變量, +擴展運算符將擴展為空字符串;如果已分配變量,則擴展為x (指定空字符串仍表示已分配)。 在這種情況下,您可以根據需要替換x (除了空字符串)。

還有${SOME_VAR:+x}變體。 區別在於空字符串::如果為變量分配空字符串,則+擴展為空字符串(如果分配了值,則+擴展為x ,即使它是空字符串)。

在我從一名前員工繼承的許多腳本中,我一直看到這種模式:

if (true $SOME_VAR)&>/dev/null; then
    ...
fi

或者這個

(true $SOME_VAR)&>/dev/null || SOME_VAR="..."

true的手冊頁說它總是返回true,因此我一直在想,這些檢查有什麼意義? 在第一種情況下,始終執行then部分,在第二種情況下,從不執行右手部分。


如果set -u (aka set -o nounset )生效,則在true $SOME_VAR $SOME_VAR時, true $SOME_VAR將失敗。 因此,這是一種測試變量是否已定義的方法。


雖然不完全一樣,

if [ x"$SOME_VAR" = x ]; then
    ...
fi

傾向於做你想做的事; 如果$SOME_VAR未定義或(差別:)定義為零長度字符串,則if為true。

如果SOME_VAR設置SOME_VAR並且設置了-u則此代碼不起作用。 我相信以下基礎知識有效: "${SOME_VAR-}" = ""


為了補充和Fred的有用答案 :

  • Bash v4.2 +中 ,可以使用較不模糊且效率較高的-v運算符測試是否定義了變量 [1] (請注意, 不能使用 $ ):
    [[ -v SOME_VAR ]]

  • 較舊的Bash版本和符合POSIX的腳本中 ,使用Fred的基於參數擴展的方法 ,這種方法也比(true ...)方法更有效。

  • 如果意圖只是提供一個默認 ,如(true $SOME_VAR)&>/dev/null || SOME_VAR="..." (true $SOME_VAR)&>/dev/null || SOME_VAR="..."成語,使用kojiro建議的(POSIX兼容)技術,也基於參數擴展
    SOME_VAR=${SOME_VAR-...} # keep $SOME_VAR value or default to '...'
    Toby Speight建議另一個符合POSIX的變體${SOME_VAR=...} ,如果未定義,它會直接使用默認值更新變量; 然而,它具有擴展到(結果)值的副作用 - 這可能是也可能不是所希望的。 抑制擴展的簡潔但有點模糊的方法是將擴展傳遞給冒號(null)實用程序( :),它會擴展,但是否則會忽略它的參數(與使用true進行相同的目的相比,它可能是略微的不那麼混亂):
    : ${SOME_VAR=...} # set $SOMEVAR to '...' only if not defined

  • 請注意,上面顯示/提到的所有參數擴展都有一個變量 ,它放在:運算符之前 ,它不僅在變量未定義時起作用,而且在定義它時也起作用但是 (包含空字符串):
    ${SOME_VAR:+...}${SOME_VAR:-...}${SOME_VAR:=...}
    可以說,這種變體行為通常是更強大的技術 ,特別是當set -uset -o nunset打開時,未定義的變量會擴展為null(空)字符串。

要添加到jwodder的解釋:

  • true $SOME_VAR周圍使用(...)來創建子shell對於這個有點模糊的測試變量存在按預期工作至關重要。

    • 如果沒有子shell, 整個腳本將中止。

    • 對子殼的需求使得該技術不僅模糊不清 ,而且效率低下 (儘管偶爾使用時這並不會引起注意)。

      • 另外, 如果set -uset -o nounset )發生不起作用,該技術會將所有變量視為已定義。
    • 使用子shell,只有子shell中止,它在其退出代碼中反映到當前shell: 1 ,如果子shell中止(變量不存在),否則為0
      因此,如果變量存在,則(true ...)命令僅評估(概念上)true。

    • &>/dev/null禁止在變量不存在時從子shell中發出的錯誤消息。

      • 拋開: true永遠不會產生任何輸出,所以使用(true $SOME_VAR)2>/dev/null (僅限stderr )就足夠了 - 這種改變使得技術符合POSIX(儘管仍然不可取)。
  • 它不只是腳本中set -uset -o nounset )語句,在訪問未定義變量的情況下打開中止 - 使用命令行選項顯式調用bash -u具有相同的效果。

[1]從Bash v4.3開始 ,您還可以測試數組變量是否具有指定索引的元素; 例如:
a=( one two ); [[ -va[0] ]]
a=( one two ); [[ -va[0] ]]成功,因為存在索引為0的數組元素; 關聯數組類似地工作。





conditional