olopopo
olopopo

Reputation: 306

What's the difference between ${var} and ${var-}

I've seen some shell scripts that make use of this variable reference notation and I just can't find any info on it.

As far as my tests have gone it is just plainly the same.

Any clues?

$ uno=1
$ if [ -n "${uno}" ]; then echo yay\! ; fi
yay!
$ if [ -n "${uno-}" ]; then echo yay\! ; fi
yay!

Upvotes: 9

Views: 1008

Answers (2)

Benjamin W.
Benjamin W.

Reputation: 52102

From the Bash manual, about parameter expansion:

${parameter:-word}

If parameter is unset or null, the expansion of word is substituted. Otherwise, the value of parameter is substituted.

In your case, word is the empty string, and the colon is omitted. Without the colon, the check is just for unset, but not for null, so ${uno-} is equivalent to checking if uno is set (see How to check if a variable is set in Bash?), and if it is not, expand it to the empty string – guaranteeing that the expansion is not unset.

It depends on the context what this is good for; in your example, it really makes no difference.

Turns out the context is a script where set -u is used – see John 1024's answer for the details.

Upvotes: 7

John1024
John1024

Reputation: 113794

${uno-} is an example of providing a default value in case the parameter uno is unset.

If uno is unset, we get the string that follows the -:

$ unset uno
$ echo ${uno-something}
something

If uno is merely the empty string, then the value of uno is returned:

$ uno=""
$ echo ${uno-something}

$

If uno has a non-empty value, of course, then that value is returned:

$ uno=Yes
$ echo ${uno-something}
Yes

Why use ${variable-}?

When proper operation of a script is important, it is common for the script writer to use set -u which generates an error message anytime an unset variable is used. For example:

$ set -u
$ unset uno
$ echo ${uno}
bash: uno: unbound variable

To handle the special cases where one may want to suppress this message, the trailing - can be used:

$ echo ${uno-}

$ 

[Credit for finding that the OP's full code used set -u and its importance to this question goes to Benjamin W.]

Documentation

From man bash

When not performing substring expansion, using the forms documented below (e.g., :-), bash tests for a parameter that is unset or null. Omitting the colon results in a test only for a parameter that is unset.

${parameter:-word}
Use Default Values. If parameter is unset or null, the expansion of word is substituted. Otherwise, the value of parameter is substituted. [emphasis added]

Upvotes: 7

Related Questions