2013-03-04 81 views
5
function wtf() { 
    echo "\$*='$*'" 
    echo "\[email protected]='[email protected]'" 
    echo "\[email protected]='"[email protected]"'" 
    echo "\[email protected]='""[email protected]""'" 
    if [ -n "$*" ]; then echo " [ -n \$* ]"; else echo "![ -n \$* ]"; fi 
    if [ -z "$*" ]; then echo " [ -z \$* ]"; else echo "![ -z \$* ]"; fi 
    if [ -n "[email protected]" ]; then echo " [ -n \[email protected] ]"; else echo "![ -n \[email protected] ]"; fi 
    if [ -z "[email protected]" ]; then echo " [ -z \[email protected] ]"; else echo "![ -z \[email protected] ]"; fi 
} 

wtf 

产生

$*='' 
[email protected]='' 
[email protected]='' 
[email protected]='' 
![ -n $* ] 
[ -z $* ] 
[ -n [email protected] ] 
[ -z [email protected] ] 

虽然在我看来,[-n [email protected]]应该是假的,因为7.3 Other Comparison Operators表明[ -n "$X" ]应对所有的$X来说都是[ -z "$X" ]的倒数。

-z

字符串为空,即,具有零长度

String='' # Zero-length ("null") string variable. 

if [ -z "$String" ] 
then 
    echo "\$String is null." 
else 
    echo "\$String is NOT null." 
fi  # $String is null. 

-n

串不为空。

-n测试要求在测试括号内引用该字符串。但是,使用带引号的字符串! -z,或者甚至仅仅在测试括号内仅引用未加引号的字符串(请参见示例7-6)通常有效,但这是不安全的做法。总是引用测试过的字符串。 [1]

我知道[email protected]是特殊的,但我不知道它是特殊的,足以违反布尔否定。这里发生了什么?


$ bash -version | head -1 
GNU bash, version 4.2.42(2)-release (i386-apple-darwin12.2.0) 

实际数字退出代码都是10按照

$ [ -n "[email protected]" ]; echo "$?" 
0 

回答

7

[email protected]是空的,"[email protected]"不会膨胀到一个空字符串;它被完全删除。所以,你的测试是不是

[ -n "" ] 

而是

[ -n ] 

现在-n不是一个运营商,而只是一个非空字符串,它总是测试为真。

+0

好的。所以'$ @'是一些词汇语法糖,它明显地触发了“-n'测试要求字符串被引用”警告。 – 2013-03-04 17:07:49

+6

这就是为什么我坚持'[['在bash中。 – choroba 2013-03-04 17:07:49

+0

@choroba:我只是验证'[[...]]'很聪明,看到'-n'缺少它的参数。 – chepner 2013-03-04 17:08:59

1

"[email protected]"不符合您的期望。它不是"$*"的不同形式,它扩展为传递给当前脚本的参数的引用列表。

如果没有参数,则它展开为空。如果存在两个参数ab c,则它扩展到"a" "b c"(即它保留参数中的空白),而"$*"扩展到"a b c"并且$*将扩展到a b c(三个词)。