对于“ GNU bash,版本4.2”之前的Bash版本-v
,该test
命令的选项是否具有等效的替代品?例如:
shopt -os nounset
test -v foobar && echo foo || echo bar
# Output: bar
foobar=
test -v foobar && echo foo || echo bar
# Output: foo
对于“ GNU bash,版本4.2”之前的Bash版本-v
,该test
命令的选项是否具有等效的替代品?例如:
shopt -os nounset
test -v foobar && echo foo || echo bar
# Output: bar
foobar=
test -v foobar && echo foo || echo bar
# Output: foo
Answers:
可移植到所有POSIX外壳:
if [ -n "${foobar+1}" ]; then
echo "foobar is defined"
else
echo "foobar is not defined"
fi
作出这样的${foobar:+1}
,如果你想治疗foobar
以同样的方式是否为空或没有定义。${foobar-}
当foobar
undefined 时,您还可以使用来获取空字符串,foobar
否则使用值(或在后面放置其他任何默认值-
)。
在ksh中,如果foobar
像一样在声明但未定义typeset -a foobar
,则${foobar+1}
扩展为空字符串。
Zsh没有声明但未设置的变量:typeset -a foobar
创建一个空数组。
在bash中,数组的行为方式不同而令人惊讶。${a+1}
仅扩展为1
if a
为非空数组,例如
typeset -a a; echo ${a+1} # prints nothing
e=(); echo ${e+1} # prints nothing!
f=(''); echo ${f+1} # prints 1
同样的原则适用于关联数组:如果数组变量具有一组非空的索引,则将它们视为已定义。
测试是否定义了任何类型的变量的另一种特定于bash的方式是检查是否在中列出了该变量。这会报告定义为空的数组,这与不同,但是会将声明但未分配的变量()报告为未定义。${!PREFIX*}
${foobar+1}
unset foobar; typeset -a foobar
case " ${!foobar*} " in
*" foobar "*) echo "foobar is defined";;
*) echo "foobar is not defined";;
esac
这等效于测试typeset -p foobar
或的返回值declare -p foobar
,除了typeset -p foobar
在声明但未分配的变量上失败之外。
在bash中,与在ksh中一样,set -o nounset; typeset -a foobar; echo $foobar
在尝试扩展未定义变量时触发错误foobar
。与ksh不同,set -o nounset; foobar=(); echo $foobar
(或echo "${foobar[@]}"
)还会触发错误。
请注意,在此处描述的所有情况下,${foobar+1}
当且仅当$foobar
会导致下的错误时,才扩展为空字符串set -o nounset
。
echo "${foobar:+1}"
中,1
如果declare -a foobar
先前已发行,则不会打印,因此foobar
是一个索引数组。declare -p foobar
正确报告declare -a foobar='()'
。是否"${foobar:+1}"
只适用于非数组变量的工作?
${foobar+1}
(不带:
,我在原始答案中倒了两个例子)对于bash中的数组是正确的。如果您的定义不同,bash有点奇怪。看到我更新的答案。$foobar
set -o nounset
0
为定义索引或键a=()
,则${a+1}
正确不返回任何内容。
defined
运算符。 Test
可以做到这一点;它不可能是困难的(呃 ......)
我对bash中的所有变量使用了相同的技术,并且可以正常工作,例如:
[ ${foobar} ] && echo "foobar is set" || echo "foobar is unset"
输出:
foobar is unset
同时
foobar=( "val" "val2" )
[ ${foobar} ] && echo "foobar is set" || echo "foobar is unset"
输出:
foobar is set
foobar=""
然后将进行报告foobar is unset
。等等,我把它拿回来。实际上,仅测试第一个元素是否为空,因此,如果您知道变量不是数组,并且只关心空性而不是定义性,那似乎只是一个好主意。
-v
不是的选项test
,而是条件表达式的运算符。