If statements in Bash let us make decisions. The basic syntax is:
if <command>; then fi
command can be a function or a program.
With what we know so far lets make a script that searches a file for some text and prints "found it!" if it finds the text.
#!/bin/bash
function main {
if grep -q $1 $2; then #(1) (2) (3)
echo "found it!"
fi
}
main $@
-
grepis a program that runs a regular expression search on the file. Regular expressions are a complicated topic and some of it will be touched on later. -
We use positional arguments
1and2. The first is the string to find. The second is the name of the file. -
-q option to grep means quiet. It suppresses output from grep.
./found-it.sh "command" bash-0-to-100.adoc found it!
Here we search of the string command in this file.
If it finds the string then grep returns 0. If not it returns 1.
This might surprise you.
In shell script 0 is true and any other value is interpreted as false.
We can also use if statements with functions we define. Let’s create a function quiet_grep which
calls grep with -q.
#!/bin/bash
function quiet_grep {
if grep -q $1 $2; then
return 0 #(1)
else
return 1
fi
}
function main {
if quiet_grep $1 $2; then #(2)
echo "found it!"
fi
}
main $@
-
Note the return value of 0 for truth.
-
Call our new function
quiet_grep.
|
Important
|
Bash uses 0 for truth and any other value as false. This is different from other programming languages.
|
Can we use if statements with variables as in other languages?
VAR=1
if $VAR; then
echo "yes"
fi
bash: 1: command not found
Doesn’t look like it. This isn’t how other languages work. What’s going on?
The reason is in the grammar of the if statement. The stuff that follows the
if has to be a command.
|
Important
|
if statements run a command. You can’t use a parameter directly in an if statement. |
If you can’t directly use a parameter in an if statement, how do you test a value of a parameter?
If statements require a command which implies that there must be a command to test parameter
values. It’s called test. You can see how to use it in the next example.
VAR=1
if test $VAR -eq 1; then #(1)
echo "yes"
fi
-
-eqis short for equals
There are many other options to test. At the command prompt type man test to see the manual for
that command. You can move up and down inside the pager using j and k. Use q to quit.
But writing test everytime I want to test something is awkward. Is there another way? Yes.
VAR=1
if [ $VAR -eq 1 ]; then #(1)
echo "yes"
fi
-
[ is also a command.
But I thought you said if statements run commands only? Yes, that’s true. [ is a command. It’s
often installed under /usr/bin.
ls -l '/usr/bin/[' -rwxr-xr-x 1 root root 59528 Mar 7 00:01 '/usr/bin/['
|
Note
|
Implementations of Bash will implement [ as a builtin command. In other words it runs in the
same process as the interpreter and the external command /usr/bin/[ isn’t called. |
Numeric and String comparisons
When comparing strings and numbers test and [ take different comparions parameters.
Generally if conventional boolean operators are used, then it’s a string comparison taking place.
If it’s -eq or -gt, single dash options, then numeric comparison is taking place.
You can see the difference in the following two examples.
In the first example numeric comparison is taking place. The values are equal. 01 and 1 are
numerically the same.
VAR=1
if [ "$VAR" -eq 01 ]; then
echo "equal"
fi
equal
In this next example we compare the same values but as strings.
#!/bin/bash
VAR=1
if [ "$VAR" = 01 ]; then
echo "equal"
else
echo "not equal"
fi
not equal
Negation and Boolean Operators
Negation uses ! like a lot of other languages to invert the truth value of an expression.
if ! true; then #(1)
echo "false"
else
echo "true"
fi
-
true is a command. If you type
which trueat the command prompt you’ll find it. There is also afalsecommand.
true
You can combine expressions using boolean operators && and ||.
#!/bin/bash
VAR1=20
VAR2=20
if [ "$VAR1" -gt 10 ] && [ "$VAR2" -gt 10 ]; then
echo "both $VAR1 and $VAR2 are greater than 10"
fi
&& applies short circuit evaluation. In other words, if the first expression is false then
the following expressions are not evaluated. A similar thing happens with ||. In this case, if the
first expression is true, then the remaining expressions are not evaluated.