26

This is code

a=''
b=john
c=${a-$b}
echo $c

And the output is empty line

And for similar code where first variable is not initialized

b1=doe
c1=${a1-$b1}
echo $c1

And the output is

doe

I do not understand how bash deals with expanding of variables leading to different results.

user1929290
  • 285
  • 1
  • 4
  • 8

1 Answers1

62

There are two variants of the ${var-value} notation, one without a colon, as shown, and one with a colon: ${var:-value}.

The first version, without colon, means 'if $var is set to any value (including an empty string), use it; otherwise, use value instead'.

The second version, with colon, means 'if $var is set to any value except the empty string, use it; otherwise, use value instead'.

This pattern holds for other variable substitutions too, notably:

  • ${var:=value}
    • if $var is set to any non-empty string, leave it unchanged; otherwise, set $var to value.
  • ${var=value}
    • if $var is set to any value (including an empty string), leave it unchanged; otherwise, set $var to value.
  • ${var:?message}
    • if $var is set to any non-empty string, do nothing; otherwise, complain using the given message' (where a default message is supplied if message is itself empty).
  • ${var?message}
    • if $var is set to any value (including an empty string), do nothing; otherwise, complain using the given message'.

These notations all apply to any POSIX-compatible shell (Bourne, Korn, Bash, and others). You can find the manual for the bash version online — in the section Shell Parameter Expansion. Bash also has a number of non-standard notations, many of which are extremely useful but not necessarily shared with other shells.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • 2
    What does the `+` mean as shown in `if test "${var+set}" = set; then` at [How can I check an environment variable?](http://gnu-autoconf.7623.n7.nabble.com/How-can-I-check-an-environment-variable-td13092.html) – jww Nov 16 '18 at 21:03
  • 1
    `${var+set}` expands to `set` if `$var` is defined (even if it is defined but empty), whereas `${var:+set}` expands to `set` if `$var` is defined and the value is not the empty string. Both expand to nothing if the variable is not set at all. Read the Bash manual on [shell parameter expansion](http://www.gnu.org/software/bash/manual/bash.html#Shell-Parameter-Expansion) for more details and more substitutions. See also [What's a concise way to check that environment variables are set in a Unix shell script?](https://stackoverflow.com/questions/307503/what/307735#307735) – Jonathan Leffler Nov 16 '18 at 21:06