0

I'm digging around in some the system files on my Mac. In /etc/profile I've found the following excerpt:

 if [ "${BASH-no}" != "no" ]; then
        [ -r /etc/bashrc ] && . /etc/bashrc
 fi

I've tried echo "${x-no}" for various choices of x and it seems like it's printing the value of x whenever x exists (i.e. has been set), and no otherwise.

Which leads me to wonder: Is this condition simply testing whether the variable x has been set?

Further questions: What exactly does - do? Is there a better way to test whether a variable has been set?

Baran Karakus
  • 193
  • 1
  • 7

2 Answers2

1

Is this condition simply testing whether the variable x has been set?

Yes, though it gets confused in the unlikely event that BASH=no.

What exactly does - do?

Here's man bash:

[...] Omitting the colon results in a test only for a parameter that is  un‐set.

   ${parameter:-word}
         Use Default Values.  If parameter is unset or null (see above),
         the expansion of word is substituted. Otherwise, the
         value of parameter is substituted.

Is there a better way to test whether a variable has been set?

Yes: [ -v BASH ]. However, this is bash specific, so it defeats the purpose of checking if the current shell is bash before doing bash specific operations.

that other guy
  • 116,971
  • 11
  • 170
  • 194
1

The meaning of ${BASH-no} is documented in §2.6.2, Parameter Expansion, of the Single Unix Specification:

${parameter:-[word]}

Use Default Values. If parameter is unset or null, the expansion of word (or an empty string if word is omitted) shall be substituted; otherwise, the value of parameter shall be substituted.

The meaning when the colon is omitted (as in your example) is described slightly later:

In the parameter expansions shown previously, use of the in the format shall result in a test for a parameter that is unset or null; omission of the shall result in a test for a parameter that is only unset.

Then there is a table, which may be easier to understand. Here are the relevant rows:

parameter
Set and Not Null
parameter
Set but Null
parameter
Unset
${parameter:-word} substitute parameter substitute word substitute word
${parameter-word} substitute parameter substitute null substitute word

Here is a reliable, portable way to check whether a variable is not set at all. Note that I am using a + modifier instead of a - modifier in the parameter expansion:

if [ "${BASH+set}" = "" ]; then
    echo 'BASH not set at all'
else
    echo 'BASH is set, perhaps to the empty string'
fi

The expansion of "${BASH+set}" can only be "" if BASH is entirely unset. If BASH is set, even to the empty string, then "${BASH+set}" expands to "set" instead.

rob mayoff
  • 375,296
  • 67
  • 796
  • 848