`test -n $ a`和`test -n" $ a"`之间的区别

时间:2017-09-19 12:11:05

标签: bash shell

$ a=""
$ test -n $a
$ echo $?
0
$ test -n a
$ echo $?
0
$ test -n "$a"
$ echo $?
1

他们之间有什么区别?为什么结果不同?

2 个答案:

答案 0 :(得分:7)

$a为空时,test -n $a会扩展为:

'test' '-n'

test只收到这样的一个参数时,它会进行默认测试,这可能是你混淆的根源。默认测试与-n相同,即以下两个是等效的:

test string
test -n string

所以你的测试是字符串-n的长度是否大于零。确实如此,因此您获得0退出状态。

你的下一个例子:

'test' '-n' 'a'

测试文字字符串a的长度是否大于零。它是,所以你再次获得0退出状态。

最后的测试可能就是你一直想要的。它扩展到:

'test' '-n' ''

现在传递了两个参数,但第二个参数为空,因此-n测试失败并且您获得1退出状态。

结论

始终引用您的变量!

您可以使用set -x查看shell如何扩展您的语句:

$ set -x
$ test -n $a
+ test -n
$ test -n "$a"
+ test -n ''

答案 1 :(得分:2)

让我们玩一个名为“统计参数”的游戏。 test在通话中收到多少个参数

test -n $a

如果您说“2”(意为-n$a),抱歉,这是不正确的。正确答案是“我们不知道”。

我们不知道,因为我们不知道参数a的值是什么。如果a=foo,则test会收到两个参数-nfoo。如果a="foo bar",那么test会在进行分词后获得三个参数,-nfoobar。< / p>

如果a=*怎么办?如果您说“2,-n*”,您可以获得积分,但您仍然错了。这是因为展开$a的结果,如果它包含某些字符,如*,则不仅会进行单词拆分,还会进行路径名扩展。在不知道当前工作目录中有多少文件的情况下,无法确定有多少参数test,因为*将扩展为一系列文件名,每个文件一个字。

相比之下,test -n "$a"总是将两个参数传递给test引用的参数扩展不受分词或路径名扩展的影响,因此a的值foofoo bar* ),确切的字符串总是作为单个参数传递给test