私がたどり着いた最も近い解決策は次のとおりです。
declare -A foobar=([foo]=bar [bar]=foo)
(set -u; true ${foobar[foo]}) 2>/dev/null
test -v
理想的には、配列キーが定義されているかどうかをテストするために使用したいと思います。しかし、test -v foobar[bar]
明らかに常に を返します1
。また、グローバルを望んでおらずset +u
、未定義の変数にアクセスするリスクがあります。
私がたどり着いた最も近い解決策は次のとおりです。
declare -A foobar=([foo]=bar [bar]=foo)
(set -u; true ${foobar[foo]}) 2>/dev/null
test -v
理想的には、配列キーが定義されているかどうかをテストするために使用したいと思います。しかし、test -v foobar[bar]
明らかに常に を返します1
。また、グローバルを望んでおらずset +u
、未定義の変数にアクセスするリスクがあります。
test -v
bash バージョン「4.2.39(1)-release」の時点で、コマンドで配列キーの存在をテストする方法がわかりません。test -v foobar[foo]
単に常に失敗します。私にとって最良のオプションは、${foobar[foo]-bar}
パラメーター置換でテストする必要があるようです。shopt のシェル オプションと新しいリリースごとに Bash の動作を再テストするためにnounset
、次の Bash シェル スクリプトを作成しました。
#!/bin/bash
shopt -os nounset
declare -ri colors=1
if (( "$colors" )); then
declare -r bold="\e[1m"
declare -r red="\e[41m"
declare -r green="\e[42m"
declare -r end="\e[0;m"
else
declare -r bold=
declare -r red=
declare -r green=
declare -r end=
fi
declare -ri a="${1:-0}"
case "$a" in
1)
echo -e "$a. Accessing ${bold}\"\$foobar\"${end} when unset should result in an error."
echo "$foobar"
;;
2)
echo -e "$a. Accessing ${bold}\"\${foobar-bar}\"${end} when unset should result in the \"bar\" default value."
echo "${foobar-bar}"
;;
3)
echo -e "$a. Accessing ${bold}\"\${foobar:-bar}\"${end} when unset should result in the \"bar\" default value."
echo "${foobar:-bar}"
;;
4)
echo -e "$a. Accessing ${bold}\"\$foobar\"${end} when set to the NULL string should result in it (whitespace)."
declare -r foobar=
echo "$foobar"
;;
5)
echo -e "$a. Accesssing ${bold}\"\${foobar-bar}\"${end} when set to the NULL string should result in it (whitespace)."
declare -r foobar=
echo "${foobar-bar}"
;;
6)
echo -e "$a. Accesssing ${bold}\"\${foobar:-bar}\"${end} when set to the NULL string should result in the \"bar\" default value."
declare -r foobar=
echo "${foobar:-bar}"
;;
7)
echo -e "$a. Accessing ${bold}\"\$foobar\"${end} when set to the \"foo\" string should result in it."
declare -r foobar=foo
echo "$foobar"
;;
8)
echo -e "$a. Accessing ${bold}\"\${foobar-bar}\"${end} when set to the \"foo\" string should result in it."
declare -r foobar=foo
echo "${foobar-bar}"
;;
9)
echo -e "$a. Accessing ${bold}\"\${foobar:-bar}\"${end} when set to the \"foo\" string should result in it."
declare -r foobar=foo
echo "${foobar:-bar}"
;;
10)
echo -e "$a. Accessing ${bold}\"\${foobar[foo]}\"${end} when unset should result in an error."
declare -rA foobar=()
echo "${foobar[foo]}"
;;
11)
echo -e "$a. Accessing ${bold}\"\${foobar[foo]-bar}\"${end} when unset should result in the \"bar\" default value."
declare -rA foobar=()
echo "${foobar[foo]-bar}"
;;
12)
echo -e "$a. Accessing ${bold}\"\${foobar[foo]:-bar}\"${end} when unset should result in the \"bar\" default value."
declare -rA foobar=()
echo "${foobar[foo]:-bar}"
;;
13)
echo -e "$a. Accessing ${bold}\"\${foobar[foo]}\"${end} when set to the NULL string should result in it (whitespace)."
declare -rA foobar=([foo]=)
echo "${foobar[foo]}"
;;
14)
echo -e "$a. Accessing ${bold}\"\${foobar[foo]-bar}\"${end} when set to the NULL string should result in it (whitespace)."
declare -rA foobar=([foo]=)
echo "${foobar[foo]-bar}"
;;
15)
echo -e "$a. Accessing ${bold}\"\${foobar[foo]:-bar}\"${end} when set to the NULL string should result in the \"bar\" default value."
declare -rA foobar=([foo]=)
echo "${foobar[foo]:-bar}"
;;
16)
echo -e "$a. Testing with ${bold}\"test -v foobar\"${end} when unset should fail."
test -v foobar
;;
17)
echo -e "$a. Testing with ${bold}\"test -v foobar\"${end} when set to the NULL string should succeed."
declare -r foobar=
test -v foobar
;;
18)
echo -e "$a. Testing with ${bold}\"test -v foobar\"${end} when set to the \"bar\" string should succeed."
declare -r foobar=
test -v foobar
;;
19)
echo -e "$a. Testing with ${bold}\"test -v foobar[foo]\"${end} when unset should fail."
declare -rA foobar=()
test -v foobar[foo]
;;
20)
echo -e "$a. Testing with ${bold}\"test -v foobar[foo]\"${end} when set to the NULL string should fail."
declare -rA foobar=([foo]=)
test -v foobar[foo]
;;
21)
echo -e "$a. Testing with ${bold}\"test -v foobar[foo]\"${end} when set to the \"bar\" string should succeed."
declare -rA foobar=([foo]=bar)
test -v foobar[foo]
;;
0)
echo -e "Testing shopt's \"nounset\" shell option with Bash version \"$BASH_VERSION\"."
echo
declare -i b
for ((b=1; b<=21; b+=1)); do
"$0" "$b"
if (( "$?" )); then
echo -e "${red}Failure.${end}"
else
echo -e "${green}Success.${end}"
fi
echo
done
;;
esac
keys=" ${!foobar[*]} "
wanted=foo
if [[ $keys == *" $wanted "* ]]; then
echo "foobar contains key $wanted"
else
echo "key $wanted not present"
fi
キーにスペースが含まれている可能性がある場合、または必要なキーがたまたま「bar foo」または連続したキーの組み合わせである場合、これは失敗する可能性があります。
更新:これは効率が悪いかもしれませんが、安全(空白に関して)であり、より明確です:
for key in "${!foobar[@]}"; do
if [[ $key = $wanted ]]; then
echo "foobar contains key $wanted"
break
fi
done