我想测试一个参数是否为空字符串""
。
当未设置该参数时,测试应该失败。
为什么下面的操作没有成功?
$ unset aa $ if [ ${aa}=="" ]; then echo yes; else echo no; fi yes
我该怎么办呢?
答案1
您的(尝试的)测试$aa == ""
相当于将两个空字符串相互比较,这会产生真实的结果。这是因为 shell 会将未设置的变量扩展为空字符串。如果 周围没有空格==
,测试将始终为真,因为它与对两个字符串的测试相同==
。该字符串始终为真。
相反,在bash
:
$ unset aa
$ if [ -v aa ]; then echo Set; else echo Not set; fi
Not set
$ aa=""
$ if [ -v aa ]; then echo Set; else echo Not set; fi
Set
因此,对空字符串的完整测试将是
if [ -v aa ] && [ -z "$aa" ]; then
echo Set but empty
fi
来自:help test
bash
-v VAR
VAR
如果设置了 shell 变量,则为 True 。
或者,从bash
手册的“条件表达式”部分:
-v varname
如果设置了 shell 变量
varname
(已分配了值),则为 True。
通过-v
测试,您可以测试变量的姓名而不是看它的价值。
如果你真的想进行字符串比较,你可以做类似的事情
if [[ "${aa-InvalidValue}" != "InvalidValue" ]] && [ -z "$aa" ]; then
echo Set but empty
fi
如果未设置,则扩展${variable-value}
将扩展至。value
variable
请注意,非常相似的内容${variable:-value}
将扩展为value
if variable
is unset或为空(空字符串)。
答案2
test
,即[
,需要在运算符周围有空格,主要是因为否则foo==
将被视为包含运算符,即使它是有效的字符串。该[[ .. ]]
结构的工作原理与此相同。 (看这个问题和Bash常见问题解答 031对比[
差异[[
。)
所以[ ${aa}=="" ]
将总是为 true,因为[ string ]
与 相同[ -n string ]
,即它测试字符串不为空。这里的字符串至少包含==
.
如果未设置或为空,则会[ ${aa} == "" ]
出现错误aa
,因为不带引号展开的空变量会消失并且[ == foo ]
不是有效的测试。如果aa
有非空值,则为 false。 ([[ ${aa} == "" ]]
即使没有引号也可以工作,因为[[ .. ]]
很特殊。)
当然[ "${aa}" == "" ]
会测试它aa
是否未设置或为空,与 相同[ -z "${aa}" ]
。
为了测试它是否为空,我们可以使用[ "${aa+x}" ] && [ -z "$aa" ]
,或者巧妙地将两者结合起来,从@Stéphane Chazelas 的回答:
if [ "${aa+x$aa}" = "x" ] ; then
echo "aa is empty but set"
fi
(这是有效的,因为如果aa
未设置,则+
扩展扩展为空字符串,如果设置了,则扩展为x$aa
,这就是x
ifaa
为空。)
$ foo() { [ "${1+x$1}" = "x" ] && echo "set but empty" || echo "unset or non-empty"; }
$ foo; foo ""; foo bar
unset or non-empty
set but empty
unset or non-empty
答案3
首先,我假设您确实知道==
它周围需要空间。的使用==
仅在 bash、ksh 和 zsh 中有效,最好使用=
。另外,测试中扩展的变量应该被引用。所以,我假设该行实际上是:
unset aa ; if [ "${aa}" = "" ]; then echo yes; else echo no; fi
至此,你的问题是:
为什么下面的操作没有成功?
因为普通 unset var 的扩展与设置为 null 的普通变量的扩展相同(来自测试“[”可以执行的操作)。
I mean, "$aa" is the same value for both an unset aa or a null aa.
要展示其工作原理,请尝试以下脚本(请注意,该脚本是 sh,它在 dash、bash、ksh 和/或 zsh 中的工作方式相同):
#!/bin/sh
blanktest(){
if [ "${aa}" = "" ]; then echo "$1 yes"; else echo "$1 no"; fi
}
unset aa; blanktest unset
unset aa; aa=""; blanktest blank
unset aa; aa="e"; blanktest value
执行时会产生:
$ ./script
unset yes
blank yes
value no
我该怎么办呢?
使用称为“使用替代值”的参数扩展。 :
${aa+x}
如果设置了变量(null 或 value),则生成 x;如果未设置变量,则生成 null。
请改用此测试:
[ "x${aa}x" = "x${aa+x}" ] && echo yes || echo no
测试脚本(同样,sh 兼容):
#!/bin/sh
blanktest(){
if [ "x${aa}x" = "x${aa+x}" ]; then echo "$1 yes"; else echo "$1 no"; fi
}
unset aa; blanktest unset
unset aa; aa=""; blanktest blank
unset aa; aa="e"; blanktest value
执行时,将打印:
$ ./script
unset no
blank yes
value no
如果您有兴趣,有几种可能的变化。