This is an old revision of the document!

The case statement


case <WORD> in
  [(] <PATTERN1> ) <LIST1> ;; # or ;& or ;;& in Bash 4
  [(] <PATTERN2> ) <LIST2> ;;
  [(] <PATTERN3> | <PATTERN4> ) <LIST3-4> ;;
  [(] <PATTERNn>) <LISTn> [;;]


The case-statement can execute commands based on a pattern matching decision. The word <WORD> is matched against every pattern <PATTERNn> and on a match, the associated list <LISTn> is executed. Every commandlist is terminated by ;;, this rule is optional for the very last commandlist (i.e. you can omit the ;; before the esac).

:V4: Bash 4 introduces new action terminators. The classic behaviour using ;; is to execute the matching block and then terminate. The ;& terminator causes case to also execute the next block, the ;;& operator makes it checking the pattern of the next block for a match. Using these terminators, a case statement can be configured to "run through" all matches, for example.

The word <WORD> is expanded using tilde, parameter and variable expansion, arithmetic, command and process substitution and quote removal, no word splitting is done, which means, you can leave expansions unquoted without problems, like:

var="test word"

case $var in
This is similar to the behaviour of the conditional expression command ("new test command") (also no word splitting for expansions).

Unlike the C-case-statement, only the matching list and nothing else is executed. If more patterns match the word, only the first match is taken. (Note the comment about :V4: Bash v4 changes above)

More patterns to match for one list to execute are separated by | (pipe symbol).


Another one of my stupid examples…

read -p "Which fruit do you like most? " fruit

case "$fruit" in
  apple)              echo "Mmmmh... I like those!"
  banana)             echo "Hm, a bit awry, no?"
  orange|tangerine)   echo "Eeeks! I don't like those!"
                      echo "Go away!"
                      exit 1
  *)                  echo "Unknown fruit - sure it isn't toxic?"

Portability considerations

See also


R.W. Emerson II, 2013/02/25 04:19

More information about the PATTERN would be helpful. Under bash 4, for example, the ABS source tells me that character types – e.g., "alnum" – can be used. But what if one wants to match a variable number of digits, for example? A comment at StackOverflow gave me the answer.

It seems that there are all sorts of possibilities! But none of them are documented under "case" in my man bash page or my info bash. (There is documentation elsewhere for patterns in general.)


The new bash 4 patterns make it possible to use case to validate replies. I need validation, because an unvalidated reply can crash the script – if I assign the reply to an integer variable, for example, and the reply is not an integer.

I think this is the code I need:

shopt -s extglob  # Must go in main line, ideally just after the shebang
# ...

read -p "Enter the message position (use sign for relative position): " tMPos

# Validate the reply (tMPos) and update the global message position (vMPos):
case "$tMPos" in
  # Positive integer? Add to curr value
  # Negative integer? Subtract from curr value
  # Unsigned integer? Replace from curr value
  # Other: Catch the error and throw it back
    echo "Reply ($tReply) not an integer"

I tested it, and it works! – though gvim doesn't much like the "]]))"!

Enter your comment. Wiki syntax is allowed:
syntax/ccmd/case.1329362730.txt · Last modified: 2012/02/16 04:25 by felipe1982

Fatal error: Out of memory (allocated 35127296) (tried to allocate 118 bytes) in /homepages/41/d13525936/htdocs/bash-hackers-site/wiki/lib/plugins/quickstats/db/php-local-browscap.php on line 28