「GNU bash、バージョン4.2」より前のBashバージョンの場合、test
コマンドの-v
オプションに相当する代替手段はありますか?例えば:
shopt -os nounset
test -v foobar && echo foo || echo bar
# Output: bar
foobar=
test -v foobar && echo foo || echo bar
# Output: foo
すべてのPOSIXシェルに移植可能:
_if [ -n "${foobar+1}" ]; then
echo "foobar is defined"
else
echo "foobar is not defined"
fi
_
空の場合も定義されていない場合もfoobar
を同じように扱いたい場合は、_${foobar:+1}
_にします。 _${foobar-}
_を使用して、foobar
が未定義の場合は空の文字列を取得し、それ以外の場合はfoobar
の値を取得できます(または_-
_の後に他のデフォルト値を配置します)。
Kshでは、foobar
が宣言されているが定義されていない場合、_typeset -a foobar
_のように、_${foobar+1}
_は空の文字列に展開されます。
Zshには宣言されているが設定されていない変数はありません。_typeset -a foobar
_は空の配列を作成します。
Bashでは、配列は別の驚くべき方法で動作します。 _${a+1}
_は、a
が空でない配列の場合にのみ_1
_に展開されます。
_typeset -a a; echo ${a+1} # prints nothing
e=(); echo ${e+1} # prints nothing!
f=(''); echo ${f+1} # prints 1
_
同じ原則が連想配列にも適用されます。配列変数は、空でないインデックスのセットがある場合、定義されたものとして扱われます。
任意のタイプの変数が定義されているかどうかをテストする別のbash固有の方法は、_${!PREFIX*}
_にリストされているかどうかを確認することです。これは、_${foobar+1}
_とは異なり、定義された空の配列を報告しますが、宣言されたが割り当てられていない変数(_unset foobar; typeset -a foobar
_)を未定義として報告します。
_case " ${!foobar*} " in
*" foobar "*) echo "foobar is defined";;
*) echo "foobar is not defined";;
esac
_
これは _typeset -p foobar
_または_declare -p foobar
_ の戻り値をテストすることと同等ですが、宣言されたが割り当てられていない変数で_typeset -p foobar
_が失敗する点が異なります。
Bshでは、kshと同様に、_set -o nounset; typeset -a foobar; echo $foobar
_は、未定義の変数foobar
を展開しようとしてエラーをトリガーします。 kshとは異なり、set -o nounset; foobar=(); echo $foobar
(または_echo "${foobar[@]}"
_)もエラーをトリガーします。
ここで説明するすべての状況で、_${foobar+1}
_が_$foobar
_でエラーを引き起こす場合に限り、_set -o nounset
_は空の文字列に展開されます。
Gillesの回答を要約すると、次のルールを作成しました。
[[ -v foobar ]]
Bashバージョン4.2以降の変数の場合。declare -p foobar &>/dev/null
Bashバージョン<4.2の配列変数。(( ${foo[0]+1} ))
または(( ${bar[foo]+1} ))
インデックス付きの下付き文字(-a
)およびキー付き(-A
)配列(declare
)それぞれ。オプション1と2はここでは機能しません。私はbashのすべての変数に同じテクニックを使用し、それは機能します、例えば:
[ ${foobar} ] && echo "foobar is set" || echo "foobar is unset"
出力:
foobar is unset
ながら
foobar=( "val" "val2" )
[ ${foobar} ] && echo "foobar is set" || echo "foobar is unset"
出力:
foobar is set