tags:

views:

119

answers:

5

Hi folks,

I am trying to check the value of an environment variable and depending on the value do certain things and it works fine as long as the variable is set. When it isn't though I get a whole bunch of errors (as BASH is trying to compare the string I specify with an undefined variable, I guess)

I tried implementing an extra check to prevent it happening but no luck. The block of code I am using is:

#!/bin/bash

if [ -n $TESTVAR ]
then
  if [ $TESTVAR == "x" ]
  then
    echo "foo"
    exit
  elif [ $TESTVAR == "y" ]
  then
    echo "bar"
    exit
  else
    echo "baz"
    exit
  fi
else
  echo -e "TESTVAR not set\n"
fi

And this is the output:

$ export TESTVAR=x
$ ./testenv.sh 
foo
$ export TESTVAR=y
$ ./testenv.sh 
bar
$ export TESTVAR=q
$ ./testenv.sh 
baz
$ unset TESTVAR
$ ./testenv.sh 
./testenv.sh: line 5: [: ==: unary operator expected
./testenv.sh: line 9: [: ==: unary operator expected
baz

My question is, shouldn't 'unset TESTVAR' nullify it? It doesn't seem to be the case...

Thanks.

+10  A: 

Enclose the variable in double-quotes.

if [ "$TESTVAR" = "foo" ]

if you do that and the variable is empty, the test expands to:

if [ "" = "foo" ]

whereas if you don't quote it, it expands to:

if [  = "foo" ]

which is a syntax error.

anon
Yup, that fixed it. Thanks for your suggestion.
Hamza
There is no need to put string literals (foo) in quotes.
camh
@camh None, except for good practice, clarity, and the fact that the real literals may contain spaces.
anon
+1  A: 

Look at the section titled "Parameter Expansion" you'll find things like:

${parameter:-word}
Use Default Values. If parameter is unset or null, the expan‐ sion of word is substituted. Otherwise, the value of parameter is substituted.

msw
That's interesting, didn't know such a thing existed. Thanks for your comment.
Hamza
+1  A: 

After interpretation of the missing TESTVAR you are evaluating [ == "y" ]. Try any of:

  • "$TESTVAR"
  • X$TESTVAR == Xy
  • ${TESTVAR:-''}
BillThor
The first one fixed it beautifully, thanks for your comment.
Hamza
+2  A: 

In Bash (and ksh and zsh), if you use double square brackets you don't need to quote variables to protect against them being null or unset.

$ if [ $xyzzy == "x" ]; then echo "True"; else echo "False"; fi
-bash: [: ==: unary operator expected
False
$ if [[ $xyzzy == "x" ]]; then echo "True"; else echo "False"; fi
False

There are other advantages.

Dennis Williamson
They have the disadvantage that the script is no longer Bourne shell compatible - which may of course not matter in this instance.
anon
@Neil: If Bourne compatibility is an issue then the shebang should say `#!/bin/sh`.
Dennis Williamson
+1  A: 

Your test to see if the value is set

if [ -n $TESTVAR ]

actually just tests to see if the value is set to something other than an empty string. Observe:

$ unset asdf
$ [ -n $asdf ]; echo $?
0
$ [ -n "" ]; echo $?
1
$ [ -n "asdf" ]; echo $?
0

Remember that 0 means True.

If you don't need compatibility with the original Bourne shell, you can just change that initial comparison to

if [[ $TESTVAR ]]
intuited