检查关联数组是否存在

T. *_*eau 7 bash

bash4.2 开始-v添加了条件表达式。它用于检查变量是否已设置(已分配值)。在编写在 下运行的脚本时,这是一个有用的工具set -o nounset,因为尝试使用未初始化的变量会导致错误。

我有一个问题,请参阅 POSIX bash( set -o posix) 中的示例:

$ declare testvar=0
$ [ -v testvar ] && echo "It works!"
It works!
$ declare -A fizz=( [buzz]=jazz )
$ [ -v fizz[buzz] ] && echo "It works!"
It works!
$ [ -v fizz ] && echo "It doesn't work :("
$ 
Run Code Online (Sandbox Code Playgroud)

如您所见,-v在常规变量上使用按预期工作。使用它来检查关联数组中字段的存在也可以按预期工作。但是,在检查关联数组本身是否存在时,它不起作用。

为什么会这样,是否有解决方法?

Pau*_*ges 1

如果您想知道它是否有任何条目,您可以检查${#fizz[@]},但这并不能告诉您它是否已被创建为空。您可以将 case 语句或其他模式匹配与错误检查结合使用。

tst() { local tst;   
  (( $# )) || return                             # *minimal* error handling...
  if tst="$(declare -p $1 2>&1)"                 # does the subshell error?
  then case "$tst" in                            # if not, check the output
       *\)*) (( $( eval echo \${#$1[@]} ) )) &&  # test number of entries
                echo "Has Args"              ||  # some implementations show '()'
                echo "Empty but defined";;       # some don't; this is for the *do*
       *-A*) echo "Empty but defined";;          # this is for the don't
          *) echo ERROR;;                        # shouldn't get here
       esac
  else echo Undefined                            # if doesn't exist
  fi
}


$: unset fizz
$: tst fizz
Undefined
$: declare -A fizz
$: tst fizz
Empty but defined
$: fizz[buzz]=jazz
$: tst fizz
Has Args
Run Code Online (Sandbox Code Playgroud)

但不知道这在您的环境中会有多大用处。请注意,我明确地为关联数组编写了这个,并进行了最少的错误检查,与这一点没有直接关系。对于任何类型的实际生产用途,都应该大幅扩展。

我不喜欢eval,但我的 bash 版本没有 namerefs。:o/