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

Работа с оператором case в Bash: понятные примеры и лучшие практики

7 min read Bash Scripting Обновлено 18 Dec 2025
Bash case: примеры, советы и шаблоны
Bash case: примеры, советы и шаблоны

Ноутбук с Ubuntu и открытым терминалом Linux

Быстрые ссылки

  • The case Statement

  • The Generic case

  • A Simple Example

  • Using Multiple Patterns in a Clause

  • Using Digits In case Statements

  • Using case Statements in for Loops

  • Handling Exit Codes With case Statements

  • Legibility Helps Maintainability

Краткое содержание

  • Оператор case в Bash делает скрипты читабельнее и проще для сопровождения по сравнению с длинными if-then-else.
  • case сравнивает выражение с наборами шаблонов в клаузаx и выполняет соответствующие команды.
  • В одном блоке можно перечислить несколько шаблонов, что сокращает и упрощает код. Числовые строки и символы также можно использовать в шаблонах.

Оператор case — простой и мощный инструмент. При возврате к старым скриптам вы оцените его ясность.

The case Statement

Большинство языков имеют аналог switch/case. Такой оператор направляет поток выполнения в зависимости от значения переменной. Для ожидаемых значений обычно задают отдельные ветки и одну ветку по умолчанию для остальных случаев.

Логически это похоже на длинную последовательность if-then с концовкой else. В Bash case пытается сопоставить выражение с одним из шаблонов, просматривая каждую клауза последовательно. Шаблоны — это строки, поэтому даже числовые значения можно сравнивать как строки.

Важно: в шаблонах можно использовать подстановочные символы Bash (globbing), например *, ?, [], и альтернативы через |.

The Generic case

Общий вид оператора case:

case expression in  
  pattern-1)
    statement
    ;;

  pattern-2)
    statement
    ;;
    .
    .
    .

  pattern-N)
    statement
    ;;

  *)
    statement
    ;;
esac

Ключевые моменты:

  • case начинается с ключевого слова case и завершается esac.
  • Выражение сравнивается с шаблонами до нахождения совпадения.
  • Двойной точка с запятой (;; ) завершает клаузу.
  • Asterisk (*) — шаблон по умолчанию.
  • Нет ограничений по числу клауз.

A Simple Example

Простой скрипт сообщает часы работы вымышленного магазина. Команда date с форматом +”%a” возвращает сокращённое имя дня недели и сохраняет его в переменной DayName.

#!/bin/bash

DayName=$(date +"%a")

echo "Opening hours for $DayName"

case $DayName in

  Mon)
    echo "09:00 - 17:30"
    ;;

  Tue)
    echo "09:00 - 17:30"
    ;;

  Wed)
    echo "09:00 - 12:30"
    ;;

  Thu)
    echo "09:00 - 17:30"
    ;;

  Fri)
    echo "09:00 - 16:00"
    ;;

  Sat)
    echo "09:30 - 16:00"
    ;;

  Sun)
    echo "Closed all day"
    ;;

  *)
    ;;
esac

Сохраните как open.sh и сделайте исполняемым:

chmod +x open.sh

Запуск:

./open.sh

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

Important: Пустая клауза по умолчанию игнорирует неподходящие варианты. Если требуется обработка ошибок — добавьте логирование или exit с кодом.

Этот вариант рабочий, но можно сделать короче и выразительнее.

Using Multiple Patterns in a Clause

Преимущество case — возможность указывать несколько альтернатив в одной клаузе через | . Это уменьшает дублирование.

Пример: определение количества дней в месяце. Всего три варианта: 28/29, 30, 31.

#!/bin/bash

shopt -s nocasematch

echo "Enter name of a month"
read month

case $month in

  February)
    echo "28/29 days in $month"
    ;;

  April | June | September | November)
    echo "30 days in $month"
    ;;

  January | March | May | July | August | October | December)
    echo "31 days in $month"
    ;;

  *)
    echo "Unknown month: $month"
    ;;
esac

Сохраняем в month.sh:

chmod +x month.sh

Запустите и протестируйте разные варианты ввода:

./month.sh

Запуск скрипта month.sh с разными вариантами ввода

shopt -s nocasematch делает сопоставление нечувствительным к регистру. Хорошая практика для пользовательского ввода.

Using Digits In case Statements

Шаблоны — строки, но вы можете использовать числовые значения как строки. Часто это полезно при простом меню или выборе опции.

#!/bin/bash

echo "Enter 1, 2, or 3: "
read Number

case $Number in

  "1")
    echo "Clause 1 matched"
    ;;

  "2")
    echo "Clause 2 matched"
    ;;

  "3")
    echo "Clause 3 matched"
    ;;

  *)
    echo "Default clause matched"
    ;;
esac
./number.sh

Запуск number.sh и различные ответы пользователя

Using case Statements in for Loops

Если нужно обработать множество выражений, поместите case внутрь цикла. Пример: классификация файлов по расширению.

#!/bin/bash

for File in $(ls)
do
  # извлечь расширение файла
  Extension=${File##*.}

  case "$Extension" in

    sh)
      echo " Shell script: $File"
      ;;

    md)
      echo " Markdown file: $File"
      ;;

    png)
      echo "PNG image file: $File"
      ;;

    *)
      echo "Unknown: $File"
      ;;
  esac
done

Сохраните как filetype.sh, сделайте исполняемым и запустите:

./filetype.sh

Запуск filetype.sh и классификация файлов

Этот шаблон полезен для пакетной обработки файлов, генерации отчётов и применения разных обработчиков в зависимости от типа.

Handling Exit Codes With case Statements

Программы возвращают код выхода: 0 — успех, >0 — ошибки (конвенция). case удобно использовать для обработки кодов выхода, особенно когда программа возвращает несколько разных кодов ошибок.

Пример с гипотетической программой go-geek, которая возвращает 0 или 1.

#!/bin/bash

go-geek

case $? in

  "0")
    echo "Response was: Success"
    echo "Do appropriate processing in here"
    ;;

  "1")
    echo "Response was: Error"
    echo "Do appropriate error handling in here"
    ;;

  *)
    echo "Unrecognised response: $?"
    ;;
esac

Сохраните в return-code.sh и сделайте исполняемым. Для тестов замените go-geek на команду, возвращающую нужный код, например попытку cd в несуществующую папку.

./return-code.sh

Запуск return-code.sh, демонстрация обработки кодов выхода

Legibility Helps Maintainability

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


Когда case не лучший выбор

  • Когда ветвление зависит от логических выражений или диапазонов (например, x > 5 и x <= 10). Тогда if/elif более естественен.
  • Когда нужна вложенная или комбинированная логика с множеством условий на одной ветке — лучше использовать функции и явные проверки.
  • Для производительных обработок больших объёмов данных в tight loops лучше избегать spawning subshells и лишних команд внутри цикла.

Альтернатива: конструкция if/elif/else — более гибкая для числовых сравнения и сложных логических условий.

Практические советы и хитрости

  • Используйте shopt -s nocasematch для нечувствительного к регистру сопоставления.
  • Экранируйте или берите в кавычки переменные с пробелами: case “$var” in …
  • Для шаблонов с подстановками используйте glob: “*.sh”) … ;; — это удобно для обработки файлов.
  • Будьте осторожны при использовании $(ls) в for; лучше использовать for File in *; do … чтобы избежать проблем с пробелами и спецсимволами в именах файлов.
  • Логируйте ветку по умолчанию и возвращайте ненулевой код выхода, если это ошибка.

Частые шаблоны (cheat sheet)

  • Обработка расширений файлов:
case "$file" in
  *.sh) echo "script" ;;
  *.py) echo "python" ;;
  *) echo "other" ;;
esac
  • Простое меню:
case $opt in
  1) do_something ;;
  2) do_something_else ;;
  q|Q) echo "quit"; exit 0 ;;
  *) echo "unknown" ;;
esac
  • Диапазоны через шаблоны (например, одна цифра):
case $d in
  [0-9]) echo "single digit" ;;
  [1-9][0-9]) echo "two digits" ;;
  *) echo "other" ;;
esac

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

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

Mermaid-диаграмма принятия решения:

flowchart TD
  A[Входное значение] --> B{Совпадает с шаблоном?}
  B -- Да --> C[Выполнить клауза]
  B -- Нет --> D{Есть ещё шаблоны?}
  D -- Да --> B
  D -- Нет --> E[Выполнить default]

Checklist для ролей

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

  • Использовать кавычки вокруг переменных с возможными пробелами
  • Добавить обработку default с логированием
  • Вынести повторяющиеся действия в функции
  • Обработать ошибки и вернуть корректный код выхода

Оператор / DevOps:

  • Проверить влияние на существующие cron‑job’ы
  • Убедиться, что скрипт исполняем и имеет корректные права
  • Тестировать с различными локалями и переводами дат

Рецензент кода:

  • Нет ли возможности сократить число веток?
  • Нет ли потенциальных проблем с пробелами в именах файлов?
  • Есть ли unit/integration тесты для основных веток?

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

  • Скрипт корректно обрабатывает все ожидаемые значения и имеет покрытие для default ветки.
  • Нет утечек оболочки: переменные корректно кавычатся, отсутствуют непредвиденные команды.
  • Возвращаемые коды: 0 при успехе, >0 при ошибке.

Сравнение с альтернативами

  • case vs if/elif: case короче и понятнее для множества конкретных значений; if/elif гибче для диапазонов и логических выражений.
  • case vs external dispatcher (Python/Perl): Bash case проще и не требует внешних зависимостей для простых задач; для сложной логики целесообразно использовать полноценный язык.

Безопасность и устойчивость

  • Избегайте использования $(ls) в конструкциях for — это ломается при пробелах в именах. Предпочтительней: for File in *; do …
  • Не выполняйте непроверенный ввод как команду через eval.
  • Для работы с путями используйте полные пути или проверяйте текущую рабочую директорию.

Миграция и совместимость

  • shopt -s nocasematch специфичен для Bash; при запуске в POSIX sh он недоступен. Если нужен перенос на dash/ash — избегайте этой опции и применяйте нормализацию через tr ‘[:upper:]’ ‘[:lower:]’.

1‑строчные определения (глоссарий)

  • case: конструкция ветвления в Bash для сопоставления с шаблонами.
  • клауза: одна ветка внутри case с шаблоном и набором команд.
  • globbing: механизм подстановки файловых шаблонов (*, ?, []).

FAQ

Q: Можно ли использовать регулярные выражения в шаблонах case?

A: Нет. case использует shell globbing, а не полноценные регулярные выражения. Для регулярных выражений используйте [[ $var =~ regex ]].

Q: Как сделать сопоставление нечувствительным к регистру без shopt?

A: Нормализуйте ввод: month=$(echo “$month” | tr ‘[:upper:]’ ‘[:lower:]’) и используйте нижний регистр в шаблонах.

Q: Почему не работает case с пробелами в имени файла?

A: Это обычно из‑за использования $(ls) в for. Используйте for File in * или while IFS= read -r; do …; done.


Итог

Оператор case — удобный и выразительный инструмент для ветвления по набору ожидаемых значений. Используйте множественные шаблоны, шорткаты для расширений файлов и аккуратно обрабатывайте ввод. Применяйте чек‑листы перед деплоем и выбирайте if/elif, если нужны логические или числовые сравнения.

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

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

Защита и аудит Docker Engine
Безопасность

Защита и аудит Docker Engine

Material You в Android 12 — настраиваем цвета
Android.

Material You в Android 12 — настраиваем цвета

Удаление неизвестных контактов в Telegram
Инструкции

Удаление неизвестных контактов в Telegram

Как поделиться заметками Kindle с друзьями
Руководство

Как поделиться заметками Kindle с друзьями

Как создать Apple ID на iPhone или iPad
Руководство

Как создать Apple ID на iPhone или iPad

Как разместить музыку на Spotify
Музыка

Как разместить музыку на Spotify