15

I'm new to shell scripting and I came across these expressions

${var:-val} and ${var-val}

${var:+val} and ${var+val}

${var:=val} and ${var=val}

so how are they evaluated and what are the differences between them

Rui F Ribeiro
  • 56,709
  • 26
  • 150
  • 232
WLION
  • 295
  • 1
  • 6

1 Answers1

11

These are all various forms of parameter expansion with alternatives:

  • ${var:-val} is replaced by val if var is unset or null, ${var} otherwise (so val is a "default value");
  • ${var:=val} first assigns val to var if var is unset or null, and then (in all cases) is replaced by ${var};
  • ${var:+val} is replaced with nothing if var is unset or null, val otherwise.

Omitting the : drops the "or null" part of all these definitions.

This is all described in the bash(1) manpage, and in POSIX.

Some examples might help:

unset a
echo "${a:-default}"

produces default, as does echo "${a-default}".

a=
echo "${a:-default}"

again produces default, but echo "${a-default}" outputs a blank line.

a=test
echo "${a:-default}"

produces test, as does echo "${a-default}".

unset a
echo "${a:=default}"

produces default, and a is now default (as confirmed by echo "${a}").

The + form might seem strange, but it is useful when constructing variables in several steps:

PATH="${PATH}${PATH:+:}/blah/bin"

will add : before /blah/bin only if PATH is non-empty, which avoids having a path starting with :.

Stephen Kitt
  • 434,908
  • 1
    The :+ form is also useful for avoiding placing the empty string as an argument on a command line, while still properly double-quoting the variable. e.g. grep ${ignorecase:+"$ignorecase"} .... The other, worse, alternative is to just use $ignorecase unquoted on the cmd line...which is only safe if you know exactly what $ignorecase can contain. – cas May 30 '16 at 12:47