Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

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"?

share|improve this question
    
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

1 Answer 1

up vote 23 down vote accepted

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
share|improve this answer
15  
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
3  
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
    
+1 Cool. Never noticed that option before. –  Joe May 11 '13 at 21:58

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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