1

To what value does an unquoted, undeclared variable expand to in order to return an exit status of 0?

Here is an example of a particular situation I ran into:

[ -n $var ]; echo $?
0

[ -n "$var" ]; echo $? 1

In both tests, the variable var is not declared. I could have saved me the hassle by testing with -z, where quoted or unquoted apparently doesn't make a difference, but I ran into this particular situation and I started wondering. I looked deeper into all the expansions that bash performs, but couldn't find any explanation for this behavior.

As a general rule I usually quote variables, but hopefully the reason of this behavior helps me better understand quoting.

twan163
  • 5,690

1 Answers1

5

The test, [ and [[ commands all act the same in that they do different things based on how many arguments they are given (excluding the closing ]/]]).

  • with 1 argument, the test will be successful if the argument is not empty
  • with 2 arguments, the arguments are treated as a unary operator (such as -n) and an operand.
  • with 3 arguments, the arguments are treated as an operand, a binary operator (such as =) and another operand
  • more than 3 arguments, test and [ give a "too many arguments" error, and [[ may give a different error (it has a more complicated parser).

Now, looking at the [ -n $var ] example, and comparing against the [[ construct. Since [[ does not do word splitting, it knows where variable values are. When var="", given [[ -n $var ]], after parameter expansion, bash will see [[ -n "" ]] which is clearly false.

But for test and [, word splitting is in effect. So [ -n $var ] becomes [ -n ] (the empty string disappears). Now, [ sees one argument which is a non-empty string, and is therefore true.

If you quote the variable: [ -n "$var" ], then you'll get the expected false result.

glenn jackman
  • 85,964