如何测试BASH 4.2中是否存在数组键



我遇到的最接近的解决方案是:

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

理想情况下,我想使用test -v测试是否定义了数组键。但是test -v foobar[bar]显然总是返回1。另外,我不希望全局set +u并承担访问未定义变量的风险。

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

作为bash版本" 4.2.39(1)-Release",我看不到如何使用test -v命令测试数组键的存在。test -v foobar[foo]总是失败。对我来说,最好的选择看起来应该用${foobar[foo]-bar}参数替换进行测试。为了通过Shopt的nounset Shell选项重新测试BASH的行为,我编写了以下bash shell脚本的每个新版本:

#!/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

相关内容

  • 没有找到相关文章

最新更新