'Bash colon operator in variable substitution?

I inherited some bash code and these two lines are bewildering me:

branch_name=`git describe --contains --all HEAD`
branch_name=${branch_name:-HEAD}

My understanding of the : colon operator is that is creates a substring based on an index so using a string, -HEAD in this case, does not make any sense.



Solution 1:[1]

In this case, the colon is just a modifier for the - operator. ${branch-HEAD} would expand to "HEAD" only if branch is unset, while ${branch:-HEAD} expands to "HEAD" if branch is the null string as well.

$ branch=master
$ echo "${branch-HEAD} + ${branch:-HEAD}"
master + master
$ branch=""
$ echo "${branch-HEAD} + ${branch:-HEAD}"
 + HEAD
$ unset branch
$ echo "${branch-HEAD} + ${branch:-HEAD}"
HEAD + HEAD

From the manual:

Omitting the colon results in a test only for a parameter that is unset.

Solution 2:[2]

In bash, ${VAR1:-VAR2} is equivalent to SQL's coalesce(VAR1, VAR2), or C#'s VAR1 ?? VAR2.

In your case:

branch_name=`git describe --contains --all HEAD`
branch_name=${branch_name:-HEAD}

The first line executes the git command and sets the value in the branch_name variable, then, the second line coalesces its value assigning the value of HEAD if branch_name is null.

As you said ${VAR1:NUM} is a string prefix operation (left in SQL), which when used with a negative number, as ${VAR1: -NUMBER} becomes a suffix (right) operation. Note the whitespace before the minus sign: if you skip that whitespace it becomes the coalesce operation as I've said before.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Matthias Braun
Solution 2 Gilles 'SO- stop being evil'