Why is my bash function returning an unexpected return code?

236 views Asked by At

I have been creating a small library of bash functions to encapsulate some of the more arcane bash syntax structures into routines that I can quickly use and reference. But for some of them, I'm running into unexpected return codes from my functions. The 'is_undefined' function below is one such example. Can anyone explain the results I am getting? (Also provided below.)

#!/bin/bash

is_undefined ()
{
  # aka "unset" (not to be confused with "set to nothing")
  # http://stackoverflow.com/questions/874389/bash-test-for-a-variable-unset-using-a-function
  [ -z ${1+x} ]
}

if [ -z ${UNDEFINED+x} ]; then
  echo "inline method reports that \$UNDEFINED is undefined"
fi

if is_undefined UNDEFINED; then
  echo "is_undefined() reports that \$UNDEFINED is undefined"
else
  echo "is_undefined() reports that \$UNDEFINED is defined"
fi

DEFINED=
if is_undefined DEFINED; then
  echo "is_undefined() reports that \$DEFINED is undefined"
else
  echo "is_undefined() reports that \$DEFINED is defined"
fi

The surprising results are:

$ ./test.sh
inline method reports that $UNDEFINED is undefined
is_undefined() reports that $UNDEFINED is defined
is_undefined() reports that $DEFINED is defined
2

There are 2 answers

0
Jan Matějka On BEST ANSWER

inside is_undefined you are testing $1, not ${UNDEFINED}, to do that you need throw in variable indirection like

is_undefined () {
    [ -z "${!1+x}" ]
}

However, that is bashism and not posix compliant. For posix compliacy you will need

is_undefined () {
    eval "[ -z \${$1+x} ]"
}
4
Olaf Dietsche On

is_undefined UDEFINED returns true, because the test inside is_undefined doesn't test UNDEFINED but $1, and $1 is defined. It's value is UNDEFINED.

So, your function should always return true, as long as you provide a parameter. The only time it will return false, should be when you call it with no arguments

is_undefined

To get is_undefined test the actual variable, you can use variable indirection with an exclamation mark !, see Shell Parameter Expansion

is_undefined ()
{
  # aka "unset" (not to be confused with "set to nothing")
  # http://stackoverflow.com/questions/874389/bash-test-for-a-variable-unset-using-a-function
  [ -z "${!1+x}" ]
}