为什么 [[ -z ]] 和 [[ -v ]] 具有不同的语法?

为什么 [[ -z ]] 和 [[ -v ]] 具有不同的语法?

如果我想执行一些给定变量未设置的命令,我正在使用:

if [[ -z "$a" || -z "$v" ]]
then
  echo "a or b are not set"
fi

然而相同的语法不适用于-v,我必须使用:

if [[ -v a && -v b ]]
then
  echo "a & b are set"
fi

这背后的历史是什么?我不明白为什么语法不一样。我读过这-v是 bash 最近添加的内容(4.2)

答案1

测试操作员-v-z只是不一样。

运算符-z判断字符串是否为空。因此,确实[[ -z "$a" ]]会给出“变量未设置”的良好近似值a,但不是完美的近似值:

  • a如果设置为空字符串而不是取消设置,则表达式将产生 true ;

  • a如果未设置并且 nounset启用了该选项,则封闭脚本将失败。

另一方面,即使在边缘情况下,-v a也将准确地“a设置变量”。应该清楚的是,传递$a而不是ato -v是不正确的,因为它会在测试操作员看到它之前扩展可能未设置的变量;因此,检查该变量(由其名称指向)并判断它是否已设置必须是该操作员任务的一部分。

答案2

-z和 的含义有所不同-v

echo Empty:
x=""  # Same with x=
[[ -z $x ]] && echo z
[[ -v  x ]] && echo v
unset x

echo Unset
[[ -z $x ]] && echo z
[[ -v  x ]] && echo v

通过使用-z,您无法区分分配了空值的变量和未分配任何值的变量。

另外,[[ -z $x ]]仍然是明智的set -u,而[[ -v x ]]不是。

相关内容