Le dichiarazioni dei casi bash possono essere messe in cascata?


29

Sto cercando di fare qualcosa del genere:

case $level in
    3)
        echo "Level Three"

    2)
        echo "Level Two"

    1)
        echo "Level one"
        ;;
esac

dove se $ level = 3, verrebbe generato

Level Three
Level Two
Level One

mentre se $ level = 1, produrrebbe solo

Level One

Ma quando lo provo, ricevo l'errore syntax error near unexpected token ')'perché non ho incluso il file ;;.

Ogni altra lingua che conosco lo consente, c'è un modo per farlo in bash? Una sorta di parola chiave che significa "ora vai avanti e fai il caso successivo come se corrispondesse"?


2
Se ogni lingua che conosci lo consente, devi imparare lingue diverse da C e dai suoi imitatori. Fallimento nelle dichiarazioni di casi sono un incidente di progettazione storica in C che in qualche modo è sopravvissuto in più lingue di principio.
Gilles 'SO- smetti di essere malvagio'

Risposte:


42

È necessario utilizzare ;&invece di ;;ottenere un comportamento fall-through:

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

Vedi la sezione Costrutti condizionali della documentazione di bash.

L'altro marcatore speciale è ;;&che:

fa sì che la shell verifichi gli schemi nella clausola successiva, se presente, ed esegua qualsiasi elenco di comandi associato su una corrispondenza corretta.

;; è sempre definitivo, non vengono testati altri schemi.

#! /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
Nota sulla portabilità: quella sintassi non è POSIX. Viene da kshed è disponibile in ksh, bash(dal 4.0, 2009) e zsh(dal 3.1.2, 1997). ;;&è specifico per bash.
Stéphane Chazelas,

4
Si noti inoltre che l' zshequivalente di bashs' ;;&è ;|(aggiunta in 4.3.3, 2007).
Stéphane Chazelas,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.