Case statements in shell script

While I do love the command-line, and will throw shell script at most problems
if it’s the right tool for the job, it’s actually fairly rare that I write
case statements.

Generally speaking, my shell scripts will usually interrogate a variable or two,
never too crazy or anything.

With that, recently I was writing a shell script for work and given the number
of conditionals I needed, it made sense to venture down the path of a case
statement.

If you’re familiar with switch statements in other languages, the case
statement is the same deal, but with slightly different syntax. Instead of
opening the statement with switch we’ll be using case and each of our
patterns to match will be inside of that (without the familiar case prefix on
each one).

Similar to how if statements are finished with a fi (if backwards), case
statements do the same, finishing up with esac:

#!/usr/bin/env bash

variable="foo"

case variable in
  # This is where our patterns to match will go...
esac

As mentioned, the patterns to match will be listed in between case and esac,
but before we list those out, let’s add a catchall (similar to default: in
other languages):

#!/usr/bin/env bash

variable='foo'

case variable in
  # This is where our other patterns to match will go...

  *)
    echo 'We did not match any other pattern'
    
esac

It’s always good to have a catchall, think of it like an else statement, which
you can use to catch unexpected values.

With the catchall in place, let’s add a couple of patterns to match again:

#!/usr/bin/env bash

variable='foo'

case variable in
  foo)
    echo 'We matched foo!'
    
  bar)
    echo 'We matched bar!'
    
  *)
    echo 'We did not match any other pattern'
    
esac

The sky’s the limit, add as many (or as few) as you need. Hopefully it’s
obvious, but if you need to a single pattern, you’re better off using an
if/then/else statement.

Now let’s say that we wanted to run the same block of code against different
patterns that are matched. You certainly could duplicate the entire pattern
block, but there’s a way better way.

The patterns listed are able to take a pipe | to list out multiple patterns to
match:

#!/usr/bin/env bash

variable='foo'

case variable in
  foo | spam)
    echo 'We matched foo or spam!'
    
  bar | eggs)
    echo 'We matched bar or eggs!'
    
  *)
    echo 'We did not match any other pattern'
    
esac

Same deal, list out as many or as few as you need!

Josh Sherman - The Man, The Myth, The Avatar

About Josh

Husband. Father. Pug dad. Musician. Founder of Holiday API, Head of Engineering and Emoji Specialist at Mailshake, and author of the best damn Lorem Ipsum Library for PHP.


If you found this article helpful, please consider buying me a coffee.