Bash provides a variety of functionalities including conditional statements. We have already looked at if-else statements and even though they get the job done, we will look at an alternative way. A case statement is easy to read when there are multiple conditional statements. Because of this, case statements are a great addition to a bash programmer's arsenal.
Case statements
First, let's look at the general syntax for case statements in bash.
case $variable in
condition-1 )
commands;;
condition-2 )
commands;;
condition-3 )
commands;;
condition-N )
commands;;
* )
commands;;
esacWe will take a look at an implementation of if-else statements in bash and then see what it will look like when we use case statements instead. We will write our script in the file script.sh.
#!/usr/bin/env bash
if [[ "${1}" == "" ]]; then
echo "No option was selected."
elif [[ "${1}" == "1" ]]; then
echo "You selected '1'."
elif [[ "${1}" == "2" ]]; then
echo "You selected '2'."
elif [[ "${1}" == "3" ]]; then
echo "You selected '3'."
else
echo "Unknown number '${1}'."
fiImplementing the same logic using case statements will look like this;
#!/usr/bin/env bash
case "${1}" in
"")
echo "No option was selected."
;;
1)
echo "You selected '1'."
;;
2)
echo "You selected '2'."
;;
3)
echo "You selected '3'."
;;
*)
echo "Unknown number '${1}'."
;;
esacWhen comparing case statements with if statements they are indeed easier to read. Case statements are pretty simple and straightforward. They check if a value matches another predefined value and execute commands based on it. The statement begins with case then we specify a value that will determine which condition to work with. After that, we write in and then set our conditions. The end of each condition is marked with ) after which its corresponding commands are written. The commands themselves end with ;;. After specifying all our conditions we may add a default case. This is done using *. We can end our case statement by writing the case command backward: esac.
The shift statement
When working with a long list of arguments, it can be ideal to skip over them after they are processed. This is where the shift command comes to our rescue. shift is a built-in bash command that moves/shifts parameters to their left. The leftmost arguments that were shifted are removed. This command takes an integer as an argument which determines how many positions should be shifted. The syntax for the command is shift n; where n is the argument for the command. In case we don't supply an argument, the default value is 1.
Let's take a look at a bash script that implements the shift command. Below we have a script that takes the answers of multiple-choice questions as parameters. Here, the examinees have the ability to skip questions to avoid negative marking. They can skip answers with either - or --.
#!/usr/bin/env bash
answers=("a" "d" "c" "a" "a")
total_score=0
for (( i = 0; i < 5; i++));
do
case "${1}" in
${answers[i]})
((total_score++))
;;
"-"|"--")
;;
*)
((total_score--))
;;
esac
shift 1
done
echo "Total score is: $total_score"Executing the program with the command below;
bash script.sh a d -- c awill give the following output:
Total score is: 2The ${1} in the case statement selects the first argument. In this case, a is passed to the case statement. The first condition of the case statement is satisfied. A score is added to total_score. The same thing happens with the second argument; d. The third argument satisfies the second condition. The fourth argument is incorrect so it satisfies the third condition in our case statement. This decreases the total_score back to 1. But the fifth argument takestotal_score back to 2.
In each iteration of the loop, the arguments are shifted to the left in this program. Because of this, ${1} can be used to capture all the arguments. Indeed, we do not have to use ${2} ${3} ${4} or ${5} to access the arguments. This makes things much more easy and simple.
Multiple arguments in a condition
As you might have noticed, the second condition has two options. Either - or -- can satisfy the condition. This is done with the help of the | bitwise operator. The | bitwise operator performs binary OR operation. This operator works somewhat like an OR logical operator which means that either - or -- can be used to skip answers without negative markings. Let's improvise our previous script file and take a look at a simple implementation of this operator:
#!/usr/bin/env bash
case "${1}" in
"")
echo "No option was selected."
;;
1 | 'a')
echo "You either selected '1' or 'a'."
;;
2 | 'b')
echo "You either selected '2' or 'b'."
;;
3 | 'c')
echo "You either selected '3' or 'c'."
;;
*)
echo "Unknown character '${1}'."
;;
esacHere, the second, third, and fourth conditions can be satisfied by either of the arguments mentioned.
Conclusion
We looked at case statements and argument parsing in detail on this topic. The major points we discussed were:-
Case statements are conditional statements just like if-else statements.
Case statements are easy to read, maintain, and debug.
The
shiftcommand helps us parse arguments by shifting them to the left.The
shiftcommand also takes integers as arguments. The syntax isshift n, where n is a positive integer.The
|bitwise operator can be used to include multiple arguments in a condition.