2. More testing constructions
- 
The compound command
[[ expression ]]Modern versions of bash include a compound command that acts as an enhanced replacement for test:
[[ expression ]]. It has also an operator for regular expression matching:=~.test-integer2.sh#!/bin/bash
# test-integer2: evaluate the value of an integer.
INT=-5
if [[ "$INT" =~ ^-?[0-9]+$ ]]; then
if [ "$INT" -eq 0 ]; then
echo "INT is zero."
else
if [ "$INT" -lt 0 ]; then
echo "INT is negative."
else
echo "INT is positive."
fi
if [ $((INT % 2)) -eq 0 ]; then
echo "INT is even."
else
echo "INT is odd."
fi
fi
else
echo "INT is not an integer." >&2
exit 1
fivim test-integer2.sh./test-integer2.shMore testing
sed -i test-integer2.sh -e '/^INT=/c INT=11'
./test-integer2.sh
sed -i test-integer2.sh -e '/^INT=/c INT='
./test-integer2.sh
sed -i test-integer2.sh -e '/^INT=/c INT=0'
./test-integer2.sh
sed -i test-integer2.sh -e '/^INT=/c INT=12'
./test-integer2.shAnother added feature of
[[ ]]is that the==operator supports pattern matching the same way pathname expansion does:FILE=foo.barif [[ $FILE == foo.* ]]; \
then echo "$FILE matches pattern 'foo.*'"; fi - 
The compound command
(( integer expression ))In addition to the compound command
[[ ]], bash also provides the compound command(( )), which is useful for operating on integers.if ((1)); then echo "It is true."; fiif ((0)); then echo "It is true."; fiif ((2)); then echo "It is true."; fiWith this test command we can simplify a bit the previous example script:
test-integer2a.sh#!/bin/bash
# test-integer2a: evaluate the value of an integer.
INT=-5
if [[ "$INT" =~ ^-?[0-9]+$ ]]; then
if ((INT == 0)); then
echo "INT is zero."
else
if ((INT < 0)); then
echo "INT is negative."
else
echo "INT is positive."
fi
if (( ((INT % 2)) == 0)); then
echo "INT is even."
else
echo "INT is odd."
fi
fi
else
echo "INT is not an integer." >&2
exit 1
fivim test-integer2a.sh./test-integer2a.shdiff -u test-integer2.sh test-integer2a.sh \
| highlight -S bash -O xterm256 2>/dev/nullNotice that we don't use a
$sign to refer to variables inside(( )). Also, instead of-eqwe use the operator==, instead of-ltwe use<, etc. This makes the syntax a bit more natural. - 
We can use logical operators to create complex expressions. For the
test(and[ ]) command the logical operators are-a(AND),-o(OR) and!(NOT). For the commands[[ ]]and(( ))they are:&&,||and!.test-integer3.sh#!/bin/bash
# test-integer3: determine if an integer is within a
# specified range of values.
MIN_VAL=1
MAX_VAL=100
INT=50
if [[ ! "$INT" =~ ^-?[0-9]+$ ]]; then
echo "INT is not an integer." >&2
exit 1
fi
if [[ "$INT" -ge "$MIN_VAL" && "$INT" -le "$MAX_VAL" ]]; then
echo "$INT is within $MIN_VAL to $MAX_VAL."
else
echo "$INT is out of range."
fi
echo -n "Using [[ ... ]]: "
if [[ ! ("$INT" -ge "$MIN_VAL" && "$INT" -le "$MAX_VAL") ]]; then
echo "$INT is outside $MIN_VAL to $MAX_VAL."
else
echo "$INT is in range."
fi
echo -n "Using (( ... )): "
if (( ! (INT > MIN_VAL && INT < MAX_VAL) )); then
echo "$INT is outside $MIN_VAL to $MAX_VAL."
else
echo "$INT is in range."
fi
echo -n "Using [ ... ] : "
if [ ! \( "$INT" -ge "$MIN_VAL" -a "$INT" -le "$MAX_VAL" \) ];
then
echo "$INT is outside $MIN_VAL to $MAX_VAL."
else
echo "$INT is in range."
fivim test-integer3.sh./test-integer3.shThe option
-nof the commandechotells it to not print a newline after the string.Notice that because
testand[are treated as commands (unlike[[and((which are special shell constructs), each argument given to them has to be separated by a space. Also, the parentheses that group logical expressions have to be escaped like this:\(and\), otherwise shell will interpret them as something else (they have a special meaning in shell).Usually it is more convenient to use
[[instead oftestor[. - 
We can use the operators
&&(AND) and||(OR) for conditional execution of a command. They can be used like this:command1 && command2First is executed
command1. If (and only if) it is successful, thecommand2is executed as well.command1 || command2First is executed
command1. If (and only if) it fails, thecommand2is executed as well.For example:
mkdir temp && cd temp[[ -d temp ]] || mkdir tempThe first one is equivalent to:
if mkdir temp; then cd temp; fiThe second one is equivalent to:
if [[ -d temp ]]; then : ; else mkdir temp; fiThe command
:is a null command, which means "do nothing". Without it we would get a syntax error.