Können Bash-Case-Anweisungen kaskadieren?

29

Ich versuche so etwas zu machen:

case $level in
    3)
        echo "Level Three"

    2)
        echo "Level Two"

    1)
        echo "Level one"
        ;;
esac

wo, wenn $ level = 3, würde es ausgeben

Level Three
Level Two
Level One

Wenn $ level = 1 ist, wird nur ausgegeben

Level One

Aber wenn ich es versuche, bekomme ich den Fehler, syntax error near unexpected token ')'weil ich den nicht mit einbezogen habe ;;.

Jede andere Sprache, die ich kenne, erlaubt dies. Gibt es eine Möglichkeit, dies in Bash zu tun? Irgendeine Art von Schlüsselwort, das bedeutet "Jetzt mach weiter und mach den nächsten Fall so, als ob er übereinstimmt"?

Benubird
quelle
2
Wenn jede Sprache, die Sie kennen, dies zulässt, müssen Sie andere Sprachen als C und seine Nachahmer lernen. Fallthrough in case-Anweisungen sind ein historischer Entwurfsunfall in C, der in prinzipientreuen Sprachen überlebt hat.
Gilles 'SO- hör auf böse zu sein'

Antworten:

42

Sie müssen Folgendes ;&verwenden ;;, um ein Fall-Through-Verhalten zu erhalten:

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

Weitere Informationen finden Sie im Abschnitt Bedingte Konstrukte in der bash-Dokumentation.

Der andere spezielle Marker ist ;;&, welcher:

Bewirkt, dass die Shell die Muster in der nächsten Klausel testet, falls vorhanden, und die zugehörige Befehlsliste bei einer erfolgreichen Übereinstimmung ausführt.

;; ist immer endgültig, werden keine weiteren Muster getestet.

#! /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
Matte
quelle
18
Hinweis zur Portabilität: Diese Syntax ist nicht POSIX. Es kommt von kshund ist verfügbar in ksh, bash(seit 4.0, 2009) und zsh(seit 3.1.2, 1997). ;;&ist bash-spezifisch.
Stéphane Chazelas
4
Beachten Sie auch, dass das zshÄquivalent von bash's ;;&ist ;|(hinzugefügt in 4.3.3, 2007).
Stéphane Chazelas