29

I'm trying to do something like this:

case $level in
    3)
        echo "Level Three"

    2)
        echo "Level Two"

    1)
        echo "Level one"
        ;;
esac

where if $level = 3, it would output

Level Three
Level Two
Level One

while if $level = 1, it would output only

Level One

But when I try it, I get the error syntax error near unexpected token ')' because I didn't include the ;;.

Every other language I know of allows this, is there a way to do it in bash? Some sort of keyword that means "now go on and do the next case as if it matched"?

  • 2
    If every language you know allows this, you need to learn languages other than C and its imitators. Fallthrough in case statements are a historical design accident in C that somehow survived in more principled languages. – Gilles May 10 '13 at 23:27
42

You need to use ;& instead of ;; to get a fall-through behavior:

#! /bin/bash
foo() {
    case "$1" in
        3)
            echo "Level Three"
            ;&
        2)
            echo "Level Two"
            ;&
        1)
            echo "Level One"
            ;;
        a)
            echo "Level a"
            ;&
        b)
            echo "Level b"
            ;&
        c)
            echo "Level c"
            ;;
    esac
}
echo 3:
foo 3
echo 2:
foo 2
echo a:
foo a
3:
Level Three
Level Two
Level one
2:
Level Two
Level one
a:
Level a
Level b
Level c

See the Conditional Constructs section of the bash documentation.

The other special marker is ;;&, which:

causes the shell to test the patterns in the next clause, if any, and execute any associated command-list on a successful match.

;; is always final, no further patterns are tested.

#! /bin/bash

foo() {
    case "$1" in
        *3*)
            echo "Level Three"
            ;;&
        *2*)
            echo "Level Two"
            ;;&
        *1*)
            echo "Level One"
            ;;&
    esac
}

echo 12:
foo 12
echo 13:
foo 13
echo 23:
foo 23
12:
Level Two
Level One
13:
Level Three
Level One
23:
Level Three
Level Two
  • 18
    Portability note: that syntax is not POSIX. It comes from ksh and is available in ksh, bash (since 4.0, 2009) and zsh (since 3.1.2, 1997). ;;& is bash-specific. – Stéphane Chazelas May 10 '13 at 13:34
  • 4
    Also note that the zsh equivalent of bash's ;;& is ;| (added in 4.3.3, 2007). – Stéphane Chazelas May 10 '13 at 14:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.