In scripting, the bash builtin case makes it easy to have more complex conditional statements without having to nest a bunch of if statements. You can selectively execute a command list or pipeline that corresponds to the first matched pattern. I know that sounds a bit confusing, but stick with us and we will have you writing case statements in no time.
Basic Syntax of Case Statements
The case statement is much different than it’s cousin the if statement. Below is an example of the basic syntax followed by a brief explanation.
case WORD in PATTERN ) Command ;; PATTERN1 | PATTERN2 | PATTERN3 ) Command ;; *) Command ;; esac
Let’s inspect the syntax line by line.
case WORD in
The above line starts the case statement by invoking case. It is followed by WORD, which is the word or expression you will try to match in the patterns that follow. This is usually a variable.
PATTERN ) Command ;;
The second line (shown above), shows the pattern you are testing for a match. You can separate several patterns with the pipe ‘|’ , as shown in the third line. The pattern list is then terminated with the end parenthesis ‘)’. You follow the patterns with the command you want to run, if your word matches those patterns. Each clause is terminated with a double semi-colon ‘;;’, a semi-colon then ampersand ‘;&’, or double semi-colon then ampersand ‘;;&’. We will outline the different operators (clause terminators?) later in the article.
*) Command ;;
The line above is the catch-all line, or default case. The asterisks ‘*’ wildcard will match any pattern. Using a catch all is optional.
You end the case statement with the word case backwards, similar to how fi closes an if statement.
BASH Case Statement Termination Operators
As mentioned above, there are three different operators available when terminating a pattern clause.
- The double semi-colon ‘;;’ will stop attempting to match patterns after the first match is found.
- The semi-colon ampersand ‘;&’ will run the command associated with the next clause. This will happen whether there is a match on the following clause or not.
- The double semi-colon ampersand ‘;;&’ will test the patterns in the rest of the clauses and only execute the command if there is a match.
The clause termination operators work in conjunction with each other. For more information on how they work see our Bash case statement video tutorial.
Bash Case Statement Example
Here is an example of a Bash case statement used in a shell script. In this example we will create a case statement that will tell us which Star Trek series a character was in. We will use a read statement to prompt for user input.
#!/bin/bash read -p "Name a Star Trek character: " CHAR case $CHAR in "Seven of Nine" | Neelix | Chokotay | Tuvok | Janeway ) echo "$CHAR is from Star Trek Voyager" ;; Archer | Phlox | Tpol | Tucker ) echo "$CHAR is from Star Trek Enterprise" ;; Odo | Sisko | Dax | Worf | Quark ) echo "$CHAR is from Star Trek Deep Space Nine" ;; *) echo "$CHAR is not in this script." ;; esac
If you read that script carefully you will notice that “Seven of Nine” is the only character that is wrapped in quotes. This is because she is the only character with spaces in her name. Wrapping the spaces in quotes allows the shell to treat the spaces as part of the pattern. There are several ways to deal with spaces or special characters in filenames or patterns.
Here is our example script in action.
Case Statement Terminator Example
In the above example we were able to find which series a Star Trek character is from using a case statement. BUT, what if a character was in multiple series? If you are a Star Trek fan you are already saying “Worf was in The Next Generation too!”. This is where the clause terminators come in handy. We can use the double semi-colon ampersand ‘;;&’ terminator to allow the script to continue searching the next clause for additional matches.
Here is our updated script, notice the ampersand sign is now terminating the clauses. We also added a new clause for characters from TNG.
#!/bin/bash read -p "Name a Star Trek character: " CHAR case $CHAR in "Seven of Nine" | Neelix | Chokotay | Tuvok | Janeway ) echo "$CHAR was in Star Trek Voyager" ;;& Archer | Phlox | Tpol | Tucker ) echo "$CHAR was in Star Trek Enterprise" ;;& Odo | Sisko | Dax | Worf | Quark ) echo "$CHAR was in Star Trek Deep Space Nine" ;;& Worf | Data | Riker | Picard ) echo "$CHAR was in Star Trek The Next Generation" ;; *) echo "$CHAR is not in this script." ;; esac
Here is the updated script in action.
Using Case Insensitive Matches with Bash Case Statements
If you want to match the pattern regardless of it’s case (Capital letters or lowercase letters) you can set the nocasematch shell option with the shopt builtin. You can do this as the first line of your script. Since the script will run in a subshell it won’t effect your normal environment.
#!/bin/bash shopt -s nocasematch read -p "Name a Star Trek character: " CHAR case $CHAR in "Seven of Nine" | Neelix | Chokotay | Tuvok | Janeway ) echo "$CHAR was in Star Trek Voyager" ;;& Archer | Phlox | Tpol | Tucker ) echo "$CHAR was in Star Trek Enterprise" ;;& Odo | Sisko | Dax | Worf | Quark ) echo "$CHAR was in Star Trek Deep Space Nine" ;;& Worf | Data | Riker | Picard ) echo "$CHAR was in Star Trek The Next Generation" && echo "/etc/redhat-release" ;; *) echo "$CHAR is not in this script." ;; esac
In this tutorial we covered the basics of using case statements in bash scripts. You should now be comfortable using case statements and understand the basics of the pattern clause terminating operators. If you have any questions or feedback sound off in the comments below.