Bash – ny harm in using variables that aren’t set

bashenvironment-variablesshell

Say I have the following code:

# Check if the color prompt is enabled and supported on this system
if [ -n "$force_color_prompt" ] && [ -x /usr/bin/tput ] && tput setaf 1 >&/dev/null; then
    GREEN="\033[1;32m"
    DIM="\033[2m"
    RESET="\033[00m"
fi

echo -e "Oh, ${GREEN}green${RESET} world, ${DIM}don't desert me now...${RESET}"

If color support is enabled, it will echo out a pretty, colored line. If color support isn't enabled, values like ${GREEN} will not have been set, and the text will print out in the usual white with black background.

The code relies on the fact that variables that aren't set will simply evaluate to an empty string (which in my tests, they do). Will this cause bugs or problems on some systems, or will all non-existent variables always evaluate to an empty string? Is there any reason I shouldn't rely on this mechanic?

Best Answer

Non-existent variables will always evaluate to an empty string when expanded as $FOO or (equivalently) ${FOO}, and there's no harm in depending on that, except in one particular case:

If someone has called set -u in the current shell before you try to use that variable, they've enabled this setting:

              -u      Treat unset variables as an error when performing param-
                      eter  expansion.   If expansion is attempted on an unset
                      variable, the shell prints an error message, and, if not
                      interactive, exits with a non-zero status.

This means that if you're writing a function that's designed to be sourced into a script that someone else is in control of, you may need to be paranoid about using unset variables - otherwise, if they used set -u prior to calling your function, their script would exit with an error message the first time you tried to expand an unset variable.

If you're writing your own script, there's no harm in counting on unset variables expanding to the empty string.

EDIT - Also, just a thought - since you're making the whole thing conditional on whether the terminfo color capabilities are available for your terminal, why not actually use terminfo to generate the sequences, rather than hardcoding the vt100 values? Something like:

if [ -n "$force_color_prompt" ] && type tput &>/dev/null; then
    GREEN="$(tput setaf 2)$(tput bold)"
    DIM="$(tput dim)"
    RESET="$(tput sgr0)"
fi

This may gain you some portability across other terminals (though, admittedly, the number of terminals that don't use the codes you showed is small and shrinking). It may also lose some portability, as some capabilities may not exist on some platforms depending on how correct the terminfo definitions are. YMMV.