2

I am learning the zsh in the conditional expressions part, and I found some unreasonable output.

For example:

$ mkdir emptyspace && cd emptyspace
$ var_assigned_with_emptystring=""

$ [[ -n $var_assigned_with_emptystring ]] && echo 'var_assigned_with_emptystring is a nonzero-len string!'
$ [[ -n "" ]] && echo '"" is a nonzero-len string!'

$ test -n $var_assigned_with_emptystring && echo 'var_assigned_with_emptystring is a nonzero-len string by test!'
var_assigned_with_emptystring is a nonzero-len string by test!
$ test -n "" && echo '"" is a nonzero-len string by test!' 

----------


$ [[ -z $var_assigned_with_emptystring ]] && echo 'var_assigned_with_emptystring is a zero-len string!'
var_assigned_with_emptystring is not an empty string!
$ [[ -z "" ]] && echo '"" is a zero-len string!'
"" is a zero-len string!

$ test -z $var_assigned_with_emptystring && echo 'var_assigned_with_emptystring is a zero-len string by test!'
var_assigned_with_emptystring is a zero-len string by test!
$ test -z "" && echo '"" is a zero-len string by test!'
"" is a zero-len string by test!

  1. Why does the test with a var_assigned_with_emptystring always gives a true result no matter it is with -n or -z option? What's the difference between test command and individual conditional expression surrounded by [[]]?

  2. What is the difference between "" and var_assigned_with_emptystring? I think the parameter should have be expended(or evaluated) to a same value as "" when it comes to process in the internal part of test function. But test -n $var_assigned_with_emptystring gives a different return status with test -n ""

0

1 Answer 1

3

This is mostly covered in Why does parameter expansion with spaces without quotes work inside double brackets "[[" but not inside single brackets "["?. In a nutshell, [[ … ]] is special syntax with different parsing rules, whereas test and [ are ordinary commands.

In plain sh (including ksh, bash, etc.), test -n $var applies splitting and globbing to the value of var due to the lack of double quotes. This doesn't happen inside double brackets.

The zsh twist is that zsh mostly doesn't require double quotes around variable expansion. However, there is one difference between $var and "$var" in list contexts such as in a command line: if a word is empty and doesn't contain any quotes, zsh removes it. So when the value of var is empty, test -n $var is the command test with one argument -n, and test with a single non-empty argument is "true". But test -n "$var" is the command test with two arguments -n and an empty string, which applies the test -n to the empty string, which is "false".

Inside [[ … ]], the empty-word removal doesn't happen, so [[ -n $var ]] and [[ -n "$var" ]] are equivalent.

Not the answer you're looking for? Browse other questions tagged .