Гид по технологиям

Bash: оператор case … esac — руководство и примеры

5 min read Bash Обновлено 14 Dec 2025
Bash case … esac — руководство
Bash case … esac — руководство

Иллюстрация синтаксиса оператора case … esac в Bash

Что такое оператор case и зачем он нужен

Оператор case в Bash — это конструкция для множественных ветвлений. По смыслу он соответствует switch/case в других языках и применяется, когда нужно проверить одно выражение на соответствие множеству образцов и вызвать разный код для каждого совпадения.

Кратко:

  • case сравнивает одно значение с набором шаблонов (glob-паттернов) и выбирает первую подходящую ветку.
  • Каждая ветка завершается последовательностью символов ;;.
  • Есть общий (catch-all) шаблон *, который сработает, если остальные не подошли.

Преимущества использования case вместо if/elif:

  • Читаемость при большом количестве вариантов.
  • Удобная запись нескольких шаблонов для одной ветки через |.
  • Поддерживает шаблоны вида *, ?, [a-z], pattern|other и т. п.

Важно: case использует шаблоны (глоб-паттерны), а не регулярные выражения.

Простой рабочий пример

Определим скрипт test.sh:

#!/bin/bash

case "${1}" in

1) echo "Option was 1!";;

2) echo "Option was 2!";;

*) echo "Option was something else: '${1}'";;

esac

Сделайте файл исполняемым и запустите с разными аргументами:

chmod +x test.sh
./test.sh 1   # Option was 1!
./test.sh 2   # Option was 2!
./test.sh foo # Option was something else: 'foo'

Разбор синтаксиса:

  • case "${1}" in — берём первый аргумент скрипта как выражение для сравнения.
  • Каждая ветка начинается с образца, затем ) и блок команд.
  • Ветку завершает ;; — это важно: одно ; внутри case не достаточно.

Пример простого case … esac в Bash

Частая ошибка: пропущенные ;;

Если использовать только один ; или не закрыть ветку правильно, Bash выдаст синтаксическую ошибку. Например, этот код не скомпилируется:

case "${1}" in
1) echo "Option 1";
2) echo "Option 2";
esac

Нужно писать ;; в конце каждой ветки.

Неправильное завершение блока в case … esac

Альтернатива через if/elif — когда подходит, когда нет

Эквивалентный пример через if/elif:

#!/bin/bash

if [ "${1}" == "1" ]; then
  echo "Option was 1!"
elif [ "${1}" == "2" ]; then
  echo "Option was 2!"
else
  echo "Option was something else: '${1}'"
fi

Если вариантов немного или условия сложные логические выражения, if/elif тоже отлично подойдёт. Но при десятках вариантов и при использовании шаблонов (напр., *.txt или [0-9]*) case выглядит компактнее и яснее.

Альтернатива case через if/then/elif/else/fi

Расширяем пример: несколько шаблонов и вложенные case

Case позволяет указывать несколько шаблонов для одной ветки через |, а также вкладывать case внутри ветки:

#!/bin/bash

case "${1}" in

1|3)
  echo "Option was 1 or 3"
  ;;

2|'a')
  case "${1}" in
    2) echo "Option was 2";;
    'a') echo "Option was 'a'";;
  esac
  ;;

*)
  echo "Option was something else: '${1}'"
  ;;

esac

Обратите внимание: вложенный case завершён esac, и после него при необходимости ставят ;; чтобы закрыть внешнюю ветку (в примере выше esac находится внутри внешней ветки, затем ;;).

Сложный пример case с дополнительными селекторами

Полезные шаблоны и приёмы

  • * — любой набор символов (включая пустую строку).
  • ? — ровно один любой символ.
  • [abc] / [a-z] — любой символ из набора или диапазона.
  • pattern1|pattern2 — перечисление альтернатив.
  • Цитирование шаблонов: если шаблон содержит пробелы или метасимволы, экранируйте или берите в кавычки.

Пример: обработка расширения файла

#!/bin/bash

file="$1"
case "$file" in
  *.sh) echo "Это shell-скрипт";;
  *.py) echo "Это Python-скрипт";;
  *.txt) echo "Это текстовый файл";;
  *) echo "Неизвестный тип файла";;
esac

Ментальные модели и эвристики

  • Представляйте case как таблицу соответствий: вход → шаблон → обработчик.
  • Если у вас много литеральных вариантов — используйте case.
  • Если нужны сложные логические выражения между несколькими переменными — if/elif может быть удобнее.
  • Для сопоставления по расширению файлов и простых паттернов — case чаще всего быстрее по чтению.

Когда case не подходит (контрпримеры)

  • Нужны сложные булевы выражения, зависящие от нескольких переменных одновременно.
  • Нужно проверять числовые диапазоны с арифметическими условиями (лучше if с арифметикой или test).
  • Нужна проверка по регулярному выражению PCRE — case использует glob-паттерны, а не полноценные регулярные выражения.

Альтернативные подходы

  • if/elif — для условий, комбинирующих несколько проверок.
  • assoc arrays (bash 4+) — когда нужно сопоставление ключ→значение, вместо ветвления.
  • grep/awk/sed — для извлечения и проверки сложных шаблонов в строках.

Практическое руководство: чеклист перед использованием case

  • Одна переменная/значение, по которому выполняется выбор.
  • Большое количество дискретных вариантов или шаблонов.
  • Не требуются регулярные выражения (glob-паттерны подходят).
  • [ ] Каждая ветка завершается ;;.
  • [ ] Обработчик по умолчанию * предусмотрен.
  • Убедитесь в корректном экранировании пробелов и специальных символов.

Критерии приёмки

  • Скрипт корректно выбирает ветку для каждого из тестовых входов.
  • Для неизвестного входа выполняется ветка *.
  • Ни одна ветка не оставляет незавершённый case (синтаксическая проверка).
  • Логирование/вывод понятен и информативен для отладки.

Тесты и контрольные случаи

  • Входы с ожидаемыми буквальными значениями (“1”, “2”).
  • Входы с шаблонными значениями (“file.sh”, “README.txt”).
  • Пустой вход (никакой аргумент) — должен сработать *.
  • Вложенные случаи: убедиться, что внешний и внутренний case корректно закрываются.

Мини-методология написания надёжного case

  1. Определите единственное выражение для проверки (переменная).
  2. Составьте список шаблонов в порядке убывания специфичности (специфичные — первыми).
  3. Добавьте обработчик по умолчанию * в конце.
  4. Для каждой ветки пишите краткие, атомарные команды; избегайте длинных логических блоков.
  5. Протестируйте все ветки и граничные случаи.

Роль-based checklist (разработчик / ревьюер)

Разработчик:

  • Писать маленькие ветки с понятными сообщениями.
  • Проверять обработку пустого аргумента.
  • Документировать нестандартные шаблоны.

Ревьюер:

  • Проверить наличие ;; в конце каждой ветки.
  • Убедиться, что вложенная логика правильно отделена и не ломает парсинг.
  • Проверить экранирование переменных и кавычек.

Безопасность и кавычки

Всегда берите переменные в кавычки в выражении case: case "${var}" in — это защищает от разбиения по словам и специальных символов. Не подставляйте в шаблоны необработанные значения пользователей без валидации, особенно если от результата зависит выполнение команд в файловой системе.

Краткое сравнение: case vs if/elif

  • Читаемость: при многих вариантов — case выигрывает.
  • Гибкость: if/elif — подходит для сложных логических условий.
  • Шаблоны: case поддерживает glob-паттерны прямо «из коробки».

Примеры расширенного использования

Обработка подкоманд (микто-CLI):

#!/bin/bash

cmd="$1"
shift

case "$cmd" in
  start)
    echo "Запуск сервиса"
    # команды запуска
    ;;
  stop)
    echo "Остановка сервиса"
    # команды остановки
    ;;
  status)
    echo "Статус сервиса"
    ;;
  *)
    echo "Неизвестная команда: $cmd"
    echo "Использование: $0 {start|stop|status}"
    ;;
esac

Советы по читабельности

  • Группируйте похожие шаблоны с помощью |.
  • Используйте пустые строки между ветками для визуального разделения.
  • Комментарии коротко объясняют нестандартные кейсы.

Глоссарий (одна строка на термин)

case — конструкция множественного ветвления в shell; pattern — glob-паттерн, используемый в case для сравнения; ;; — маркер окончания ветки case;

  • — универсальный (catch-all) шаблон.

Резюме

Оператор case … esac в Bash — мощный и читабельный инструмент для выбора кода по множеству шаблонов. Он особенно хорош для обработки подкоманд, расширений файлов и любых случаев, где необходимо сопоставление единого входа со многими вариантами. Правильное использование ;;, | и шаблонов делает код устойчивым и понятным.

Небольшая шпаргалка: всегда кавычьте переменные в case, не забывайте ;;, используйте * для ветки по умолчанию и группируйте шаблоны через |.

Удачи и приятного кодинга!

Поделиться: X/Twitter Facebook LinkedIn Telegram
Автор
Редакция

Похожие материалы

RDP: полный гид по настройке и безопасности
Инфраструктура

RDP: полный гид по настройке и безопасности

Android как клавиатура и трекпад для Windows
Гайды

Android как клавиатура и трекпад для Windows

Советы и приёмы для работы с PDF
Документы

Советы и приёмы для работы с PDF

Calibration в Lightroom Classic: как и когда использовать
Фото

Calibration в Lightroom Classic: как и когда использовать

Отключить Siri Suggestions на iPhone
iOS

Отключить Siri Suggestions на iPhone

Рисование таблиц в Microsoft Word — руководство
Office

Рисование таблиц в Microsoft Word — руководство