Advanced BASH Variable Usage

Basic Variable Usage

  • $VARIABLE
  • ${VARIABLE}

BASH variables are case sensitive, e.g. $VARIABLE is not the same as $variable. The curly bracket syntax allows the variable name to be delimited from trailing characters that otherwise might be interpreted as part of the variable name:

VARIABLE=end
echo "The opposite of having an $VARIABLE is being $VARIABLEless"
The opposite of it having an end is being

echo "The opposite of having an $VARIABLE is being ${VARIABLE}less"
The opposite of having an end is being endless

Also, to access positional parameters beyond the 9th ($9):

set one two three four five six seven eight nine ten
echo "Argument  1 : $1"    # First positional parameter = one
echo "Argument 10?: $10"   # First positional parameter + 0 = one0
                           # Equivalent to ${1}0
echo "Argument 10 : ${10}" # Tenth positional parameter = ten

When using arrays the curly bracket syntax must always be used:

${ARRAY[1]}

BASH also has the builtin capability to manipulate its variables in ways that you might otherwise use external commands for.

Case Modification

  • ${VARIABLE^}
  • ${VARIABLE^^}
  • ${VARIABLE,}
  • ${VARIABLE,,}
  • ${VARIABLE~}
  • ${VARIABLE~~}

These operators cause $VARIABLE to be interpreted as:

^ first character capitalized test Test
^^ all characters capitalized test TEST
, first character lower cased TEST tEST
,, all characters lower cased TEST test
~ first character has its case reversed TeSt teSt
~~ all characters have their case reversed TeSt tEsT

Removing Substrings with Globbing

  • ${VARIABLE#PATTERN}
  • ${VARIABLE##PATTERN}
  • ${VARIABLE%PATTERN}
  • ${VARIABLE%%PATTERN}

This syntax will return only part of $VARIABLE's value, where PATTERN signifies what to remove. The pattern uses globbing (like command line matching). The # syntax is a non-greedy match from the beginning of the variable's value, whereas ## is a greedy match from the beginning. The same goes for the % syntax, except that it's non-greedy from the end of the variable's value, and %% is greedy from the end. The matching is anchored either at the beginning (#) or end (%), so there is no substring removal from the middle of a string.

VARIABLE="The quick brown fox jumps over the lazy dog"
echo ${VARIABLE#*r} # remove everything up to and including the first "r"
own fox jumps over the lazy dog
echo ${VARIABLE##*e } # remove everything up to and including the last "e "
lazy dog
echo ${VARIABLE%r*} # remove everything from the end until the last "r"
The quick brown fox jumps ove
echo ${VARIABLE%%e *} # remove everything from the end until the first "e "
Th

Search and Replace

  • ${VARIABLE/SEARCHPATTERN/REPLACEMENT}
  • ${VARIABLE//SEARCHPATTERN/REPLACEMENT}
  • ${VARIABLE/SEARCHPATTERN}
  • ${VARIABLE//SEARCHPATTERN}

Like removing a substring the number of /'s changes the behavior of this syntax. A single / replaces to first instance found, whereas // will replace all occurrences. Patterns again use globbing, like the command line and are greedy. If a REPLACEMENT string is not provided then the pattern is removed from the variable's value.

VARIABLE="Success consists of going from failure to failure without loss of enthusiasm."

echo ${VARIABLE/failure/victory}
Success consists of going from victory to failure without loss of enthusiasm.

echo ${VARIABLE//failure/victory}
Success consists of going from victory to victory without loss of enthusiasm.

echo ${VARIABLE/of}
Success consists  going from failure to failure without loss of enthusiasm.

echo ${VARIABLE//of}

Success consists  going from failure to failure without loss enthusiasm.
echo ${VARIABLE/Success /} # This is the same as ${VARIABLE/Success }
consists of going from failure to failure without loss of enthusiasm.

The globbing can also be anchored at the beginning or end of the variable's contents by using # (beginning), or % (end).

VARIABLE=0000

echo ${VARIABLE/#0/1}
1000

echo ${VARIABLE/%0/1}
0001

String Length

Simple and straight forward. Returns the number of characters in the contents of the variable.

VARIABLE=0123456789

echo ${#VARIABLE}
10

Substring by Offset

  • ${VARIABLE:OFFSET}
  • ${VARIABLE:OFFSET:LENGTH}

Part of the contents of variable can be returned using numerical offsets either explicitly provided or as result of an arithmetic expression.

VARIABLE="I have not failed. I’ve just found 10,000 ways that won’t work."

echo ${VARIABLE:19}
I’ve just found 10,000 ways that won’t work.

To visualize what just happened: (substring starts at character 19)
~~I have not failed. ~~I've just found 10,000 ways that won't work.

A negative offset starts the substring that number of characters from the end, and if provided the length still counts forward. The minus (-) does need to be separated from the colon, otherwise the syntax is interpreted as setting a default value -- description coming up next.

echo ${VARIABLE: -16}
that won’t work.

echo ${VARIABLE:(-16):10}
that won't

Let's work out what this did: (substring starts 16 characters from the end)
~~I have not failed. I've just found 10,000 ways ~~that won't work.
and: (substring starts 16 characters from the end, and is 10 characters long)
I have not failed. I've just found 10,000 ways that won't work.

If your copy of BASH is new enough (Bash 4.2-alpha) then a negative length is also accepted. With this syntax the string between the offset number of characters from the beginning until the length of characters from the end is returned.

echo ${VARIABLE:19:-17}
I’ve just found 10,000 ways

For this one: (substring starts at character 19 and ends 17 characters from the end)
I have not failed. I've just found 10,000 ways that won't work.

If both the offset and the length are negative then the string between the character first numbered character from the end to the second numbered character from the end is substring presented.

echo ${VARIABLE: -28:-17}
10,000 ways

Results in: (substring starts 28 characters from the end and ends 17 characters from the end)

I have not failed. I've just found -28>10,000 ways<-17 that won't work.

Setting an Default Value to be Returned

  • ${VARIABLE:-DEFAULT}
  • ${VARIABLE-DEFAULT}

The :- syntax will set a default value for a variable, different from the substring syntax in the section above where the minus and colon are separated. The default value can be another variable or hard-coded value. The :- syntax will return the default value if the variable is either unset (never initialized with a value) or empty (null).

DEFAULT="Dubito ergo cogito; cogito ergo sum."

echo ${VARIABLE:-$DEFAULT}
Dubito ergo cogito; cogito ergo sum.

VARIABLE="I exist"
echo ${VARIABLE:-$DEFAULT}
I exist

VARIABLE=
echo ${VARIABLE:-$DEFAULT}
Dubito ergo cogito; cogito ergo sum

The second syntax using only a minus (-) works the same way except the default value is only returned if the variable is unset, but not if it has been emptied.

echo ${VARIABLE-$DEFAULT}
    # nothing is returned

unset VARIABLE
echo ${VARIABLE-$DEFAULT}
Dubito ergo cogito; cogito ergo sum.

echo ${EMPTYVAR-$DEFAULT}
Dubito ergo cogito; cogito ergo sum.

EMPTYVAR=
echo ${EMPTYVAR-$DEFAULT}
    # nothing is returned

Assigning a Default Value

  • ${VARIABLE:=DEFAULT}
  • ${VARIABLE=DEFAULT}

Similar to above except the default value is assigned to the variable if the variable is unset or empty. Likewise, using only an equal sign (=) will assign the default value to the variable only if the variable is unset, but not if it is empty (null).

DEFAULT="What you seek is seeking you."

echo ${VARIABLE:=$DEFAULT}
What you seek is seeking you.

echo $VARIABLE
What you seek is seeking you.

VARIABLE=
echo ${VARIABLE=$DEFAULT}
    # nothing is returned

unset VARIABLE
echo ${VARIABLE=$DEFAULT}
What you seek is seeking you.

echo $VARIABLE
What you seek is seeking you.

Provide an Alternate Value

  • ${VARIABLE:+ALTERNATE}
  • $VARIABLE+ALTERNATE}

This syntax will return nothing if the variable is unset or empty, but if it is set then rather than the value of the variable being returned the alternate value is returned. Like above using only the plus sign (+) will return the alternate value if the parameter is set or empty, but will return nothing if the variable is unset.

ALTERNATE="The absence of alternatives clears the mind marvelously."

echo ${VARIABLE:+$ALTERNATE}
    # nothing is returned

VARIABLE="An alternative."
echo ${VARIABLE:+$ALTERNATE}
The absence of alternatives clears the mind marvelously.

VARIABLE=
echo ${VARIABLE+$ALTERNATE}
The absence of alternatives clears the mind marvelously.

unset VARIABLE
echo ${VARIABLE+$ALTERNATE}
    # nothing is returned

Returning an Error if Empty or Unset

  • ${VARIABLE:?ERROR}
  • ${VARIABLE?ERROR}

When using the :? syntax BASH will print an error to STDERR if the variable is unset or empty (null), but if it is set then the value will be returned. In the case of an error the return code is also set to a non-zero value. In the case of just the question mark (?) an error will only be printed if the variable is unset, but return the value of the variable if it is set or empty (null).

ERROR="Most deadly errors arise from obsolete assumptions."

echo ${VARIABLE:?$ERROR}
-bash: VARIABLE: Most deadly errors arise from obsolete assumptions.
echo $?
1

VARIABLE=
echo ${VARIABLE:?$ERROR}
-bash: VARIABLE: Most deadly errors arise from obsolete assumptions.
echo ${VARIABLE?$ERROR}

VARIABLE="Update assumptions."
echo ${VARIABLE?$ERROR}
Update assumptions.