19. Conditional Constructs
Bash is not only a command line interpreter, it is also a programing language. Therefore its include conditional constructs like the if command. The evaluation is done by examining the return status of the command lists following the if or elif keywords. On finding an exit status of 0 all consequent commands are executed:
$ if [ 0 -lt 1 ]
then
echo "0 is lower than 1"
elif [ 1 -lt 2 ]
then
echo "1 is lower than 2"
fi
The second condition is never proofed. If no command list exits by 0, Bash executes the alternate consequent commands within the else section:
if [ 1 -lt 0 ]
then
echo "1 is lower than 0"
else
echo "1 is never lower than 0"
fi
Bash even supports the case command. Bash matches the word between "case" and "in" against a list of patterns. If one list matches, Bash executes the corresponding commands:
$ case "orange" in
orange) echo "almost sweet";;
lemon) echo "never sweet";;
esac
Alternatives are separated by the "|" operator:
$ case "melone" in
orange|banana|melone) echo "almost sweet";;
lemon) echo "never sweet";;
esac
The "*" operator matches every word:
$ case "quince" in
orange|banana|melone) echo "almost sweet";;
lemon) eho "never sweet";;
*) echo "never eaten this fruit";;
esac
Unless the nocasematch option is set, Bash regards the matching to the alphabetical order. If the matching command list ends by ;; no further procession takes place. If ending on ;& the following command list will executed also:
$ case "quince" in
orange|banana|melone) echo "almost sweet";;
quince) echo "not eatable";&
lemon) echo "never sweet";;
*) echo "never eaten this fruit";;
esac
If ends on ;;& the following pattern list will also be matched.
$ case "orange" in
orange) echo "almost sweet";;&
melone|orange) echo "smells great";;
esac
The word undergoes tilde expansion, parameter expansion, command substitution, arithmetic expansion and quote removal. Each pattern undergoes tilde expansion, parameter expansion, command substitution and arithmetic expansion:
$ case ~$USER in
~$USER) echo "found string"
esac
An arithmetic expression is also a conditional expression. It returns 0 if the expression is expanded to a value not 0. Otherwise 1 is returned:
$ (( 1 > 0 )) && echo "arithmetic expressions returns successfuly"
Conditional expressions are evaluated by the test command:
$ test ! -z $USER && echo "varaible is not null"
or in between the "[ ... ]" and "[[ ... ]]" operators. A true expression exits on 0, a false on 1:
$ [ 1 -gt 0 ] && [[ 1 -gt 0 ]] && echo "both expressions are true"
Words can be compared lexicographically according to the current locale by the "<" or ">" operator:
$ [ a > b ] && echo "TODO examine"
The "[[ ... ]]" does no word splitting nor filename expansion on conditional expressions. Tilde expansion, parameter expansion, arithmetic expansion, command substitution and quote removal takes place:
$ [[ $USER = "pa" ]] && [[ ~ = "/home/pa" ]] && [[ $((2*2)) -eq 4 ]] && echo "expansions allowed"
To match a word against a pattern the "==" (equal) or "!=" (not equal) operators are used. The right side is taken as pattern as described in the section about filename expansion:
$ [[ "Oranges and lemons" == *and* ]] && echo "pattern matches"
Double quoted patterns are compared by string comparison with the left side:
$ [[ "say the bells of St. Clement's." != " B.." ]] && echo "strings not equal"
To match a word against a regular expression the "=~" operator is used:
$ [[ "Oranges and lemons" =~ e. ]] && echo "match extended regular expression"
The matches and their sub matches can be referenced by round brackets. They are saved in the array BASH_REMATCH:
$ [[ "A Clockwork Orange." =~ ( Clock.+ (Or(.+)))e ]] && echo ${BASH_REMATCH[*]}
Clockwork Orange Clockwork Orang Orang angr
Within the "[[ ... ]]" operator expressions can be combined by Boolean operators. To check both expressions to be true, the "&&" (AND) operator is used:
$ [[ 1 -eq 1 && 0 -ne 1 ]] && echo "both expressions are true"
To check at least one expression is true, the "||" (OR) operator is used:
$ [[ 1 -eq 1 || 0 -eq 1 ]] && echo "at least one expressions is true"
To negate an expression, the "!" operator is used:
$ [[ ! 0 -eq 1 ]] && echo "the negation of a wrong expression is true"
The order of evaluation can be grouped with brackets. The expression within the innermost braket is evaluated first:
$ [[ 0 -eq 1 && (1 -eq 1 || 0 -eq 0) ]] || echo "expression is evaluated to false"
Surrounding first two expressions by brackets:
$ [[ (0 -eq 1 && 1 -eq 1) || 0 -eq 0 ]] && echo "expression is evaluated to true"