「GNU bash、バージョン4.2」より前のBashバージョンの-v
場合、test
コマンドのオプションに同等の代替手段はありますか?例えば:
shopt -os nounset
test -v foobar && echo foo || echo bar
# Output: bar
foobar=
test -v foobar && echo foo || echo bar
# Output: foo
「GNU bash、バージョン4.2」より前のBashバージョンの-v
場合、test
コマンドのオプションに同等の代替手段はありますか?例えば:
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:+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固有の別の方法は、にリストされているかどうかを確認することです。これは、とは異なり、定義済みとして空の配列を報告しますが、宣言されているが未割り当ての変数()は未定義として報告します。${!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
です。
kashと同様に、bashではset -o nounset; typeset -a foobar; echo $foobar
、未定義の変数を展開しようとするとエラーが発生しますfoobar
。kshとは異なり、set -o nounset; foobar=(); echo $foobar
(またはecho "${foobar[@]}"
)もエラーをトリガーします。
ここで説明するすべての状況で、でエラーが発生する${foobar+1}
場合にのみ空の文字列に展開することに注意してください。$foobar
set -o nounset
echo "${foobar:+1}"
では1
、declare -a foobar
以前に発行されたためfoobar
、インデックス付き配列である場合は出力されません。declare -p foobar
正しく報告しdeclare -a foobar='()'
ます。い"${foobar:+1}"
非配列変数のためだけの仕事を?
${foobar+1}
(:
元の回答では、2つの例を逆にした)がbashの配列に対して正しいです。定義が異なる場合、bashは少し奇妙です。更新された回答をご覧ください。$foobar
set -o nounset
0
インデックスもキーもtrueとして定義されていない場合a=()
、${a+1}
正しく何も返しません。
defined
演算子があります。 Test
それを行うことができます。それは(難しいことはできませんええと ......)
私は、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
foobar=""
つまり、それを報告しfoobar is unset
ます。待って、それを取り戻す。本当に最初の要素が空かどうかだけをテストするので、変数が配列ではないことを知っていて、空ではなく定義されていることだけを気にするのが良い考えのようです。
-v
はのオプションではなく、test
条件式の演算子です。