Могут ли случаи с bash каскадными?


29

Я пытаюсь сделать что-то вроде этого:

case $level in
    3)
        echo "Level Three"

    2)
        echo "Level Two"

    1)
        echo "Level one"
        ;;
esac

где, если $ level = 3, это вывело бы

Level Three
Level Two
Level One

в то время как если бы $ level = 1, он вывел бы только

Level One

Но когда я пробую это, я получаю ошибку, syntax error near unexpected token ')'потому что я не включил ;;.

Любой другой язык, который я знаю, позволяет это, есть ли способ сделать это в bash? Какое-то ключевое слово, которое означает «теперь продолжай и делай следующий случай, как если бы он соответствовал»?


2
Если все языки, которые вы знаете, позволяют это, вам нужно изучать языки, отличные от C и его подражателей. Падение в case-заявлениях - это исторический случай проектирования в C, который каким-то образом сохранился в более принципиальных языках.
Жиль "ТАК - перестань быть злым"

Ответы:


42

Вы должны использовать ;&вместо того, ;;чтобы получить провал поведение:

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

Смотрите раздел Условные конструкции документации bash.

Другой специальный маркер ;;&, который:

заставляет оболочку тестировать шаблоны в следующем предложении, если таковые имеются, и выполнять любой связанный список команд при успешном совпадении.

;; всегда окончательно, дальнейшие шаблоны не проверяются.

#! /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
Примечание о переносимости: этот синтаксис не POSIX. Оно происходит от kshи доступен в ksh, bash(начиная с 4.0, 2009) и zsh(с 3.1.2, 1997). ;;&является специфичным для bash.
Стефан Шазелас

4
Также обратите внимание , что zshэквивалентно bash«s ;;&в ;|(добавлен в 4.3.3, 2007).
Стефан Шазелас
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.