8

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!
Benjamin W.
  • 46,058
  • 19
  • 106
  • 116
olopopo
  • 296
  • 1
  • 8

2 Answers2

6

${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]

John1024
  • 109,961
  • 14
  • 137
  • 171
  • Take a closer look, that has a colon in it's syntax so it's not the same – olopopo May 18 '16 at 17:11
  • 3
    @olopopo The colon is addressed in the quote from the manual. – Benjamin W. May 18 '16 at 17:12
  • Ok, that bold text made me realize. Thanks and sorry for my obfuscation! – olopopo May 18 '16 at 17:17
  • @BenjaminW. so in the case of just referring to the variable as ${uno-} doesn't make any difference. That was my question in the first place BTW – olopopo May 18 '16 at 17:21
  • @olopopo It makes a difference if `uno` is unset. – Benjamin W. May 18 '16 at 17:24
  • @BenjaminW. hmmm sorry but I guess in this particular case it does not apply: `unset uno ; if [ -n "${uno}" ]; then echo yay\! ; fi ; if [ -n "${uno-}" ]; then echo yay\! ; fi` – olopopo May 18 '16 at 17:27
  • You can take a look at the script if you like [https://github.com/mesosphere/marathon-lb/blob/master/run] – olopopo May 18 '16 at 17:33
  • 1
    @olopopo Ah. The important point there is `set -u` ("treat unset variables as an error when substituting"). Try this: `set -u; unset var` and then `[[ -n ${var-} ]]` vs `[[ -n ${var} ]]`. – Benjamin W. May 18 '16 at 17:39
5

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.

Community
  • 1
  • 1
Benjamin W.
  • 46,058
  • 19
  • 106
  • 116