看一个字符串是否为空,可以通过 -n 或
-z来判断。按照操作符的意义,变量VAR而言,如果VAR为空或未定义,那么-n测试结果应该为假,而-z应该为真。反之,如果不空,则-n为真,-z为假。
采用条件测试的列表形式,即“[ -n $VAR ] && echo TRUE”,如果输出TRUE,则表明条件测试结果为真。
经过测试,显然VAR不空时,测试结果都正常,而VAR为空,测试结果也是真,但很多手册指南什么的(包括ABS《Advance Bash Scripting Guide》的示例7.1),都说这个应该可以正常工作,原因何在?
将上面语句写入脚本,并用bash -x 执行,发现测试条件成为了“‘[‘ -n ‘]‘”,也就是说经过分词处理之后, 为空的变量实际上消失了,测试命令变成了只有“-n”这么一个参数,而查bash手册(bash4.2)中关于test(与‘[‘命令等价,
注意“[”实际上是一个命令)命令求值的解释,发现只有一个参数而且参数不空的时候,求值都为真。也就是说,将 “-n”换成别的什么测试操作符,比如“-z”或“-e”,测试结果都是真。一试,果不其然。
解决办法是什么呢?
方法一,不直接使用变量${VAR},而是后面附加一个任意字符,然后比较与此字符是否相等来测试,变量是否为空。 比如“[ ${VAR}y == y ] && echo TRUE”,会输出TRUE,而“[
${VAR}y != y ] && echo TRUE”就不会输出。
方法二,使用“if [[ conditional-expression ]] ”的形式。其中“[[”是关键字而不是命令。这种形式下“[[ ... ]]”不会 进行分词处理,所以用bash
-x执行脚本,发现“[[ -n $VAR ]]”成了“[[ -n ‘‘ ]]”,就是说空串依然作为一个参数(即
‘‘)保存下来了,根据test的求值规则,这是两个参数了,所以测试操作符就能正常工作了。这样一看,ABS强调尽量用“[[ ... ]]”结构还是很有道理的。