As declarações do caso bash podem ter uma cascata?

29

Estou tentando fazer algo assim:

case $level in
    3)
        echo "Level Three"

    2)
        echo "Level Two"

    1)
        echo "Level one"
        ;;
esac

onde se $ level = 3, ele produziria

Level Three
Level Two
Level One

enquanto se $ level = 1, ele produziria apenas

Level One

Mas quando tento, recebo o erro syntax error near unexpected token ')'porque não incluí o ;;.

Qualquer outra linguagem que conheço permite isso, existe uma maneira de fazer isso no bash? Algum tipo de palavra-chave que significa "agora prossiga e faça o próximo caso como se correspondesse"?

Benubird
fonte
2
Se todos os idiomas que você conhece permitirem, você precisará aprender outros idiomas além de C e seus imitadores. A descoberta das declarações de caso é um acidente histórico de design em C que de alguma forma sobreviveu em idiomas mais baseados em princípios.
Gilles 'SO- stop be evil'

Respostas:

42

Você precisa usar em ;&vez de ;;obter um comportamento de falha:

#! /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

Consulte a seção Construções condicionais da documentação do bash.

O outro marcador especial é ;;&:

faz com que o shell teste os padrões na próxima cláusula, se houver, e execute qualquer lista de comandos associada em uma correspondência bem-sucedida.

;; é sempre final, nenhum outro padrão é testado.

#! /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
Esteira
fonte
18
Nota de portabilidade: essa sintaxe não é POSIX. Ela vem do kshe está disponível em ksh, bash(desde 4.0, 2009) e zsh(desde 3.1.2, 1997). ;;&é específico do bash.
Stéphane Chazelas
4
Observe também que o zshequivalente a bash's ;;&é ;|(adicionado em 4.3.3, 2007).
Stéphane Chazelas