case
The case statement matches a variable or command output against patterns and branches execution accordingly. It provides a clean way to handle multiple values, making it ideal for processing command-line arguments and building menu-driven scripts.
Syntax
case variable in
pattern1)
action1
;;
pattern2 | pattern3)
action2
;;
*)
default action
;;
esac
Pattern List
| Pattern | Description |
|---|---|
| word) | Exact match. Executes when the value equals word. |
| pat1 | pat2) | OR condition. Executes when the value matches either pattern. |
| *.txt) | Wildcard pattern. Matches any string ending in .txt. |
| [aeiou]) | Character class. Matches any one of the characters a, e, i, o, or u. |
| ?) | Matches exactly one character. ??) matches two characters, ???) matches three. Useful for fixed-length patterns. |
| [0-9]) | Range character class. Matches any one digit from 0 to 9. |
| [!a-z]) | Negated character class. Matches any single character that is NOT a lowercase letter. |
| *) | Default pattern that matches everything. Place it last. |
| ;; | Terminates a pattern block (does not fall through to the next pattern). |
| ;& | Falls through and executes the next pattern block regardless (Bash 4+). |
| ;;& | Evaluates the next pattern and executes it if it matches (Bash 4+). |
Sample Code
Branches execution based on a command-line argument. Use | to combine multiple values into a single OR condition.
sample_service.sh
#!/bin/bash
action=$1
case "$action" in
start)
echo "Starting the service"
;;
stop)
echo "Stopping the service"
;;
restart | reload)
echo "Restarting the service"
;;
status)
echo "Checking service status"
;;
*)
echo "Usage: $0 {start|stop|restart|reload|status}"
exit 1
;;
esac
Run the following command:
bash service.sh restart Restarting the service
Uses wildcard patterns to determine a file type by its extension.
sample_filetype.sh
filename="report.pdf"
case "$filename" in
*.php | *.py | *.rb)
echo "Script file"
;;
*.txt | *.md | *.csv)
echo "Text file"
;;
*.jpg | *.png | *.gif)
echo "Image file"
;;
*.pdf)
echo "PDF file"
;;
*)
echo "Unknown file type"
;;
esac
Run the following command:
bash filetype.sh PDF file
Uses the character class [0-9] to check a numeric range.
sample_grade_case.sh
score=85
case $score in
9[0-9] | 100)
echo "A (Excellent)"
;;
8[0-9])
echo "B (Good)"
;;
7[0-9])
echo "C (Pass)"
;;
*)
echo "D (Fail)"
;;
esac
Run the following command:
bash grade_case.sh B (Good)
? is a wildcard that matches exactly one character. It is useful when matching against a fixed-length input. For example, ???) matches three characters and ?????) matches five characters. This makes it convenient for validating ZIP codes, fixed-length IDs, and similar formats.
sample_zip_check.sh
zip=$1
case "$zip" in
???-????)
echo "Japanese ZIP code format (3 digits - 4 digits)"
;;
?????)
echo "5-digit number (US ZIP or legacy format)"
;;
?)
echo "Only one character was entered"
;;
"")
echo "Empty string"
;;
*)
echo "Unrecognized format"
;;
esac
Run the following command:
bash zip_check.sh 100-0001 Japanese ZIP code format (3 digits - 4 digits) bash zip_check.sh 12345 5-digit number (US ZIP or legacy format) bash zip_check.sh A Only one character was entered
? means "exactly one character", not "one or more characters". ??) matches strings of length 2 — it does not match a 1-character or 3-character string. To match an arbitrary number of characters, use * instead.
Common Mistakes
Common Mistake 1: Forgetting ;; causes fall-through to the next pattern
Each case block must end with ;;. Without it, execution falls through to the next block and produces unexpected results.
service_ng.sh
#!/bin/bash
action=$1
case "$action" in
start)
echo "Starting service"
# ;; is missing here
stop)
echo "Stopping service"
;;
esac
The following example demonstrates this:
bash service_ng.sh start Starting service Stopping service
Terminating each block with ;; ensures only the intended block executes.
service_ok.sh
#!/bin/bash
action=$1
case "$action" in
start)
echo "Starting service"
;;
stop)
echo "Stopping service"
;;
esac
Run the following command:
bash service_ok.sh start Starting service
Common Mistake 2: Passing an unquoted variable with spaces breaks matching
If the variable contains spaces and is not quoted, the shell splits it into multiple words before matching, causing the case statement to fail unexpectedly.
case_unquoted_ng.sh
#!/bin/bash
msg="hello world"
case $msg in
"hello world")
echo "matched"
;;
*)
echo "no match"
;;
esac
Run the following command:
bash case_unquoted_ng.sh no match
Quoting the variable preserves spaces and allows the pattern to match correctly.
case_quoted_ok.sh
#!/bin/bash
msg="hello world"
case "$msg" in
"hello world")
echo "matched"
;;
*)
echo "no match"
;;
esac
Run the following command:
bash case_quoted_ok.sh matched
Notes
Case patterns use shell glob patterns (wildcards), not regular expressions. If you need regex matching, use the =~ operator with if / [[ ]].
Separating patterns with | lets you group OR conditions into a single block. Compared to if-elif chains, case is more concise and easier to read.
The default pattern *) is optional, but it is recommended to always include it to handle unexpected input gracefully.
If you find any errors or copyright issues, please contact us.