case - оператор для множественного ветвления, заменяющий цепочки операторов if/then/else

Пример

case "$var" in
  yes ) echo "glad u agreed" ;;
  no )
    echo "sorry; good bye"
    exit
  ;;
  * ) echo "Invalid answer. try again" ;;
esac

Круглые скобки в case

Для каждой закрывающей скобки в синтаксисе case есть возможность поставить открывающую круглую скобку: (“yes”) вместо “yes”) в примере выше.
Ставить открывающую скобку необязательно + зачем лишний символ?

Мощь case в поддержке сопоставления с шаблонами (это также и идиоматический подход):

case "$var" in
  [Nn][Oo]* )    # здесь, как вариант, писать комменты
    echo "Нет, так, нет"
    exit
  ;;
  [Yy]?? | [Ss]ure | [Oo][Kk]* )
    echo "Ok, glad we agree"
  ;;
  * ) echo "Try again"
    continue
  ;;
esac
 
# Оператор case в bash
last | latest) some_cmd ;;
 
# пример простой документации:
index )     # Комментарий
  # Пример:
    # какой-нибудь пример
    # примеррррр
  some_cmd --some-arg
;;

В примере выше использовал подстановочные знаки командной строки, которые обычно используются при передаче filenames. Есть три подстановочных знака:

ЗнакExplain
?любой символ
*любые символы
[ ]любой из символов внутри них

Из примера выше:
Конструкция [Nn][Oo]* соответствует, например: no, nO, NO, noway, Not Ever .
Вертикальная черта ( | ) - это, по сути, логическое “ИЛИ”, то есть, шаблону [Yy]?? | [Ss]ure | [Oo][Kk]* будут соответствовать: Yes, yes, YES, yEs, yES, yup, Sure, sure, OK, ok, OKfine, OK why not.

* )- это вариант по умолчанию, то есть, шаблон, совпадающий с чем угодно. Если ни с одним из предыдущих шаблонов совпадений не было найдено - с этим найдется всегда. Поэтому его и помещают последним в списке.

Шаблоны - это не RegEx

Короче, если нужны RegEx-ы - используй if/then/else конструкцию, а не case.

Про символы ;;

Символы ;; означают, что ничего дальше не нужно делать, то есть, bash, встретив эти символы, закончит всю логику внутри case перейдет к следующей инструкции после esac. Bash после этих символов завершает выполнение оператора case.

Но если нужно, чтобы bash проверял и другие варианты в case (или выполнял другие действия) можно использовать комбинации символов ;;& и ;& . Наглядно:

case $filename in
  ./*) echo -n "local"         # Начинается с ./
    ;&                         # Спуститься к СЛЕДУЮЩЕМУ варианту
  [^/]*) echo -n "relative"    # Начинается с любого символа, кроме /
    ;;&                        # Проверить совпадения с ДРУГИМИ вариантами
  /*) echo -n "absolute"       # Начинается с /
    ;&                         # Спуститься к СЛЕДУЮЩЕМУ варианту
  */*) echo "pathname"         # В имени есть /
    ;;                         # Завершить
  *) echo "filename"           # Вcё остальное
    ;;                         # Завершить
esac

Шаблоны в примере будут сравниваться по порядку со значением $filename.

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

read num
case $num in
  1) echo 1 ;&
  2) echo 2 ;;
esac

То есть, в случае выше, если даже будет введен 1 выведется и 2.

А ;;& говорит проверить другие варианты по порядку.
Т.к. применение этих символов не особо понятно не знакомым с bash людям - лучше тщательно комментировать код (или юзать if/else/elif).


Соус: Книга Идиомы Bash Глава 3. На всякий случай: оператор Case