-v
「GNU bash、バージョン4.2」より前のBashバージョンにこのコマンドオプションと同等の選択肢はありますかtest
?たとえば、
shopt -os nounset
test -v foobar && echo foo || echo bar
# Output: bar
foobar=
test -v foobar && echo foo || echo bar
# Output: foo
答え1
すべてのPOSIXシェルに移植可能:
if [ -n "${foobar+1}" ]; then
echo "foobar is defined"
else
echo "foobar is not defined"
fi
${foobar:+1}
foobar
空であっても定義されていなくても、同じ方法で処理するには、そうします。定義されていない${foobar-}
場合は空の文字列を取得するためにfoobar
使用することができます。そうでない場合は値を取得するために使用することもできfoobar
ます-
。
kshでは、foobar
宣言されているが定義されていない場合は空の文字列に展開されますtypeset -a foobar
。${foobar+1}
Zsh変数は宣言されていませんが、設定されていません。typeset -a foobar
空の配列を作成します。
Bashでは、配列はさまざまで驚くべき方法で動作します。空でない配列の場合にのみ${a+1}
拡張されます。1
a
typeset -a a; echo ${a+1} # prints nothing
e=(); echo ${e+1} # prints nothing!
f=(''); echo ${f+1} # prints 1
同じ原則が連想配列に適用されます。配列変数に空でないインデックスセットがある場合、配列変数は定義された配列変数と見なされます。
どのタイプの変数が定義されているかをテストする別のbash関連の方法は、その変数がundefedとして報告されていることを確認することです。${!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
宣言されているが割り当てられていない変数では失敗します。
bashでは、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
答え2
Gilesの答えをまとめて、次のルールを開発しました。
[[ -v foobar ]]
Bashバージョン> = 4.2で使用される変数。declare -p foobar &>/dev/null
Bash バージョン < 4.2 で使用するための配列変数です。(( ${foo[0]+1} ))
または、(( ${bar[foo]+1} ))
インデックス配列(-a
)とキー-A
配列()declare
の下付き文字としてそれぞれ使用します。オプション1と2はここでは機能しません。
答え3
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