Search code examples
variablesposixsh

Posix shell: distinguish between empty and not existing variable


In pure /bin/sh how can I distinguish between an empty variable, an unset variable and a not existing (not defined) variable.

Here are the case:

# Case 1: not existing
echo "${foo}"

# Case 2: unset
foo=
echo "${foo}"

# Case 3: Empty
foo=""
echo "${foo}"

Now I would like to check for each of those three cases. If case 2 and case 3 are actually the same, then I must at least be able to distinguish between them and case 1.

Any idea?

UPDATE Solved thanks to Matteo

Here is how the code looks like:

#foo  <-- not defined
bar1=
bar2=""
bar3="a"

if ! set | grep '^foo=' >/dev/null 2>&1; then
    echo "foo does not exist"
elif [ -z "${foo}" ]; then
    echo "foo is empty"
else
    echo "foo has a value"
fi

if ! set | grep '^bar1=' >/dev/null 2>&1; then
    echo "bar1 does not exist"
elif [ -z "${bar1}" ]; then
    echo "bar1 is empty"
else
    echo "bar1 has a value"
fi

if ! set | grep '^bar2=' >/dev/null 2>&1; then
    echo "bar2 does not exist"
elif [ -z "${bar2}" ]; then
    echo "bar2 is empty"
else
    echo "bar2 has a value"
fi


if ! set | grep '^bar3=' >/dev/null 2>&1; then
    echo "bar3 does not exist"
elif [ -z "${bar3}" ]; then
    echo "bar3 is empty"
else
    echo "bar3 has a value"
fi

And the results:

foo does not exist
bar1 is empty
bar2 is empty
bar3 has a value

Solution

  • You can use set

    If no options or arguments are specified, set shall write the names and values of all shell variables in the collation sequence of the current locale. Each name shall start on a separate line, using the format:

    You can list all the variables (set) and grep for the variable name you want to check

    set | grep '^foo='