¿Puede bash las declaraciones de casos en cascada?

29

Estoy tratando de hacer algo como esto:

case $level in
    3)
        echo "Level Three"

    2)
        echo "Level Two"

    1)
        echo "Level one"
        ;;
esac

donde si $ level = 3, generaría

Level Three
Level Two
Level One

mientras que si $ nivel = 1, solo generaría

Level One

Pero cuando lo intento, aparece el error syntax error near unexpected token ')'porque no incluí el ;;.

Todos los demás idiomas que conozco permiten esto, ¿hay alguna manera de hacerlo en bash? ¿Algún tipo de palabra clave que significa "ahora continúe y haga el siguiente caso como si coincidiera"?

Benubird
fuente
2
Si todos los idiomas que conoces lo permiten, debes aprender otros idiomas además de C y sus imitadores. El fracaso en las declaraciones de casos es un accidente de diseño histórico en C que de alguna manera sobrevivió en lenguajes con más principios.
Gilles 'SO- deja de ser malvado'

Respuestas:

42

Debe usar en ;&lugar de ;;obtener un comportamiento fallido:

#! /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 la sección Construcciones condicionales de la documentación de bash.

El otro marcador especial es ;;&, que:

hace que el shell pruebe los patrones en la siguiente cláusula, si existe, y ejecute cualquier lista de comandos asociada en una coincidencia exitosa.

;; siempre es final, no se prueban más patrones.

#! /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
Estera
fuente
18
Nota de portabilidad: esa sintaxis no es POSIX. Viene de kshy está disponible en ksh, bash(desde 4.0, 2009) y zsh(desde 3.1.2, 1997). ;;&es específico de bash.
Stéphane Chazelas
44
También tenga en cuenta que el zshequivalente de bash's ;;&es ;|(agregado en 4.3.3, 2007).
Stéphane Chazelas