2013-03-04 14 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 

produkuje

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

choć wydaje mi się, że powinno być fałszywe [-n [email protected]] ponieważ 7.3 Other Comparison Operators[ -n "$X" ] wskazuje, że powinien być odwrotnością [ -z "$X" ] dla wszystkich $X.

-z

ciąg jest zerowy, to znaczy ma zerową długość

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

ciąg nie jest null.

Test -n wymaga, aby ciąg był cytowany w nawiasach testowych. Używanie niecytowanego ciągu znaków z ! -z lub nawet samego nienotowanego ciągu w nawiasach testowych (patrz Przykład 7-6) zwykle działa, jednak jest to praktyka niebezpieczna. Zawsze cytuj testowany ciąg. [1]

Wiem, że [email protected] jest wyjątkowy, ale nie wiedziałem, że to było na tyle szczególne, aby naruszać negację boolowską. Co tu się dzieje?


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

Rzeczywiste kodów numerycznych wyjścia są 1 lub 0 według

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

Odpowiedz

7

[email protected] Po opróżnieniu "[email protected]" nie rozszerza się do pustego ciągu; jest całkowicie usunięty. Więc test nie jest

[ -n "" ] 

ale raczej

[ -n ] 

Teraz -n nie jest operator, ale tylko niepusty ciąg znaków, który zawsze sprawdza jako prawdziwe.

+0

Ok. Więc '$ @' to jakiś leksykalny cukier syntaktyczny, który nieuchronnie wyzwala test "-n", wymaga, aby ciąg był cytowany "uwaga". –

+6

Dlatego trzymam się '[[' w bash. – choroba

+0

@choroba: Właśnie sprawdzałem, czy '[[...]] 'jest wystarczająco inteligentny, aby zobaczyć, że' -n' brakuje argumentu. – chepner

1

"[email protected]" nie robi tego, czego się spodziewasz. Nie jest to inna forma "$*", rozwija się do cytowanej listy argumentów przekazanych do bieżącego skryptu.

Jeśli nie ma żadnych argumentów, rozwija się do zera. Jeżeli istnieją dwa argumenty a i b c, a następnie rozszerza się "a" "b c" (to znaczy zachowuje odstępy w argumenty), a "$*" rozszerza się "a b c" i $* rozwinie się do a b c (trzech słów).