从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在常规变量上使用按预期工作。使用它来检查关联数组中字段的存在也可以按预期工作。但是,在检查关联数组本身是否存在时,它不起作用。
为什么会这样,是否有解决方法?
如果您想知道它是否有任何条目,您可以检查${#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/