Main index

Introducing UNIX and Linux


More on shells

Overview
Simple arithmetic
      Arithmetic expansion
            Operators for arithmetic expansion
      The 'expr' command
Pattern matching
      Patterns
            Examples of patterns
      The case statement
Entering and leaving the shell
More about scripts with options
Symbolic links
Setting up terminals
Conventions used in UNIX file systems
Summary
Exercises

The case statement

A statement that involves pattern matching is case. It works by starting off with

case expression in

where expression has a value (and would typically be a variable preceded by $). Following that, there is a sequence of

pattern) command-list  ;;

and the case statement is terminated with esac. The value of expression is evaluated, and the first of the patterns that matches it has the following command-list executed. For example, a very simple version of the command file, which only examines the suffix of its first argument, might look like:

case $1 in
  *.c)      printf "%s:   %s\n" "$1" "c program text" ;;
  *.a)      printf "%s:   %s\n" "$1" "archive library" ;;
  *.o)      printf "%s:   %s\n" "$1" "object file" ;;
  *)        printf "%s:   %s\n" "$1" "unknown type" ;;
esac
Where patterns appear in a case statement they are matched with the expression at the start of the case statement, and not with any filenames. If a pattern appears within a command-list in a case statement, however, the pattern is matched to filenames as before. Double semicolons are required, because a single semicolon is used to separate multiple commands occurring on a single line. The following script lists the files in the current directory, but asks you whether you wish to list the 'dot' files:
echo "List dot files as well? "  # Prompt user
read YESORNO                     # Read reply

case "$YESORNO" in               # Check reply
   [Yy]*)   ls * .* ;;           # Commence with a Y?
   [Nn]*)   ls * ;;              # Commence with an N?
   *)       echo "Sorry, don't understand";;
esac

Note the technique used here for asking the user a yes/no question - the answer is assumed to commence with a Y or an N, in upper or lower case, and that is sufficient. This script would happily accept input Yqwerty as a positive response. If you required the user to type in exactly the word YES, the pattern, instead of [Yy]*, would be [Yy][Ee][Ss].

Worked example

Write a script named compile to take a single argument representing the name of a program written in a high-level language, and then compile that program using one of cc (for C), pc (for Pascal) or f77 (for FORTRAN). File suffixes .c, .p and .f respectively are assumed to indicate the language type.
Solution: We need to check the file suffix using a case statement.

# First, check we do have a single argument
case $# in
   1)  ;;
   *) echo "$0: Incorrect number of arguments";;
esac

# Now examine the suffix of argument 1
case $1 in
   *.c) cc $1 ;;
   *.p) pc $1 ;;
   *.f) f77 $1 ;;
   *)   echo "Unknown language";;
esac

The names for the compilers may be different on your system, and are not specified in POSIX.

Where the same command is required for two separate patterns, rather than duplicating the line (or lines) of commands, you can combine the two (or more) patterns. So the pattern

sam|chris

would match either sam or chris.

Worked example

Write a script to read in a string representing a telephone number as dialled from the UK, and indicate whether it is an overseas number (commencing 00 or 010), a value added number (commencing 0898 or 0891), a freephone number (commencing 0800), a service number (three digits commencing with a 1) or a national code (ten digits commencing 0 or eleven digits commencing 01).
Solution: We could use many if statements, but the script would be very messy. This is the sort of problem for which a case statement is ideal.

# Prompt user and read in the number
printf "Input phone number: "
read N

# Examine the various patterns that might match N
case $N in
  00*|010*)    echo "International" ;;
  0898*|0891*) echo "Value added" ;;
  0800*)       echo "Freephone" ;;
  1??)         echo "Service number" ;;
  0?????????)  echo "National code (pre 1995)" ;;
  01?????????) echo "National code (after 1995)" ;;
  *)           echo "Unknown code" ;;
esac

Copyright © 2002 Mike Joy, Stephen Jarvis and Michael Luck