Оператор case

Заменяем длинную лесенку if-elif на читаемый выбор по шаблону.

case — это конструкция выбора, которая сопоставляет значение с набором шаблонов и выполняет ветку первого совпавшего.

Когда case удобнее if

Если нужно сравнить одну переменную с несколькими вариантами, цепочка if-elif-elif выглядит громоздко. case делает это чище:

read -r action
case "$action" in
  start)
    echo "Запускаю сервис"
    ;;
  stop)
    echo "Останавливаю сервис"
    ;;
  restart)
    echo "Перезапускаю сервис"
    ;;
  *)
    echo "Неизвестная команда: $action"
    ;;
esac

Каждая ветка заканчивается двумя точками с запятой ;;, а *) — ветка по умолчанию (как default). Закрывается всё словом esac (case наоборот).

Шаблоны, а не только точные значения

Сила case в том, что ветки — это шаблоны как у имён файлов. * — любой текст, ? — один символ, | — «или».

file="photo.JPG"
case "$file" in
  *.jpg|*.JPG|*.png)
    echo "Это картинка"
    ;;
  *.txt)
    echo "Это текст"
    ;;
  *)
    echo "Неизвестный тип"
    ;;
esac

Вывод:

Это картинка

Шаблон *.jpg|*.JPG|*.png ловит файлы с любым из трёх расширений.

Как работает под капотом

Bash сопоставляет значение с шаблонами сверху вниз и выполняет ПЕРВЫЙ совпавший, после чего сразу выходит из case (в отличие от switch в C, тут нет «проваливания» в следующие ветки). Шаблоны используют тот же механизм, что и раскрытие имён файлов (globbing), но без обращения к диску — сравнивается только строка. Поэтому порядок веток важен: более общий шаблон * ставят последним.

Частые ошибки

  • Забыли ;; в конце ветки. Без них Bash выдаст синтаксическую ошибку.
  • Поставили * первым. Тогда он перехватит всё, и остальные ветки не сработают.
  • Ждать регулярных выражений. В case работают глоб-шаблоны (*, ?), а не regex; . там обычная точка.

Итог

  • case заменяет длинные if-elif при сравнении одной переменной с вариантами.
  • Ветки — глоб-шаблоны (*, ?, |), каждая закрывается ;;.
  • Ветка *) — по умолчанию, её ставят последней; конструкция закрывается esac.
Проверьте себя
1. Чем заканчивается каждая ветка внутри case?
Abreak
Bточкой с запятой ;
Cдвумя точками с запятой ;;
Dfi
2. Что означает ветка *) в case?
AОшибку
BВетку по умолчанию для любого значения
CКонец конструкции
DКомментарий
3. Какие шаблоны понимает case?
AРегулярные выражения
BГлоб-шаблоны: *, ? и | для перечисления
CТолько точные строки
DSQL-шаблоны с %