$ a=""
$ test -n $a
$ echo $?
0
$ test -n a
$ echo $?
0
$ test -n "$a"
$ echo $?
1
他们之间有什么区别?为什么结果不同?
答案 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
会收到两个参数-n
和foo
。如果a="foo bar"
,那么test
会在进行分词后获得三个参数,-n
,foo
和bar
。< / p>
如果a=*
怎么办?如果您说“2,-n
和*
”,您可以获得积分,但您仍然错了。这是因为展开$a
的结果,如果它包含某些字符,如*
,则不仅会进行单词拆分,还会进行路径名扩展。在不知道当前工作目录中有多少文件的情况下,无法确定有多少参数test
,因为*
将扩展为一系列文件名,每个文件一个字。
相比之下,test -n "$a"
总是将两个参数传递给test
。 引用的参数扩展不受分词或路径名扩展的影响,因此a
的值foo
,foo bar
或*
),确切的字符串总是作为单个参数传递给test
。