1

私がたどり着いた最も近い解決策は次のとおりです。

declare -A foobar=([foo]=bar [bar]=foo)
(set -u; true ${foobar[foo]}) 2>/dev/null

test -v理想的には、配列キーが定義されているかどうかをテストするために使用したいと思います。しかし、test -v foobar[bar]明らかに常に を返します1。また、グローバルを望んでおらずset +u、未定義の変数にアクセスするリスクがあります。

4

2 に答える 2

0

test -vbash バージョン「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
于 2012-11-24T13:30:59.773 に答える
0
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
于 2012-11-02T20:13:57.473 に答える