如何测试参数是否已设置为空字符串?

如何测试参数是否已设置为空字符串?

我想测试一个参数是否为空字符串""

当未设置该参数时,测试应该失败。

  1. 为什么下面的操作没有成功?

    $ unset aa
    $ if [ ${aa}=="" ]; then echo yes; else echo no; fi
    yes
    
  2. 我该怎么办呢?

答案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 testbash

-v VARVAR如果设置了 shell 变量,则为 True 。

或者,从bash手册的“条件表达式”部分:

-v varname

如果设置了 shell 变量varname(已分配了值),则为 True。

通过-v测试,您可以测试变量的姓名而不是看它的价值。


如果你真的想进行字符串比较,你可以做类似的事情

if [[ "${aa-InvalidValue}" != "InvalidValue" ]] && [ -z "$aa" ]; then
    echo Set but empty
fi

如果未设置,则扩展${variable-value}将扩展至。valuevariable

请注意,非常相似的内容${variable:-value}将扩展为valueif variableis 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,这就是xifaa为空。)

$ 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

如果您有兴趣,有几种可能的变化。

相关内容