Как использовать операторы case в сценариях Bash
Операторы case в Bash эффективны, но при этом просты в написании. Когда вы вернетесь к старому скрипту Linux, вы будете рады, что использовали оператор case
вместо длинного оператора if-then-else
.
Заявление о деле
Большинство языков программирования имеют свою версию оператора switch
или case
. Они направляют поток выполнения программы в соответствии со значением переменной. Как правило, существует ветвь выполнения, определенная для каждого из ожидаемых возможных значений переменной, и одна универсальная или по умолчанию ветвь для всех остальных значений.
Логическая функциональность аналогична длинной последовательности операторов if-then
с оператором else
, перехватывающим все, что ранее не обрабатывалось одним из if
операторы.
Реализация case
в Bash пытается сопоставить выражение с одним из предложений. Он делает это, по очереди просматривая каждое предложение, пытаясь найти соответствующий шаблон. Шаблоны в предложениях — это строки, но, как это ни парадоксально, это не означает, что мы не можем использовать числовые значения в качестве выражения.
Общий случай
Общая форма оператора case
такова:
case expression in pattern-1) statement ;; pattern-2) statement ;; . . . pattern-N) statement ;; *) statement ;; esac
- Инструкция
case
должна начинаться с ключевого словаcase
и заканчиваться ключевым словомesac
. - Выражение оценивается и сравнивается с шаблонами в каждом предложении до тех пор, пока не будет найдено совпадение.
- Выполняется оператор или операторы в соответствующем предложении.
- Двойная точка с запятой «
;;
» используется для завершения предложения. - Если шаблон найден и операторы в этом предложении выполнены, все остальные шаблоны игнорируются.
- Количество предложений не ограничено.
- Звездочка «
*
» обозначает шаблон по умолчанию. Если выражение не соответствует ни одному из других шаблонов в оператореcase
, выполняется предложение по умолчанию.
Простой пример
Этот скрипт сообщает нам часы работы воображаемого магазина. Он использует команду 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
, чтобы сделать его исполняемым. Вам нужно будет сделать это для всех сценариев, которые вы создадите по мере работы с этой статьей.
chmod +x open.sh
Теперь мы можем запустить наш скрипт.
./open.sh
День, когда был сделан снимок экрана, приходится на пятницу. Это означает, что переменная DayName
содержит строку «Пт». Это соответствует образцу «Пт» в предложении «Пт».
Обратите внимание, что шаблоны в предложениях не нужно заключать в двойные кавычки, но это не повредит, если они будут. Однако вы должны использовать двойные кавычки, если шаблон содержит пробелы.
Предложение по умолчанию оставлено пустым. Все, что не соответствует ни одному из предыдущих предложений, игнорируется.
Этот сценарий работает, и его легко читать, но он многословен и повторяется. Мы можем довольно легко сократить этот тип оператора case
.
Использование нескольких шаблонов в предложении
Очень удобная функция операторов case
заключается в том, что вы можете использовать несколько шаблонов в каждом предложении. Если выражение соответствует любому из этих шаблонов, операторы в этом предложении выполняются.
Вот скрипт, который говорит вам, сколько дней в месяце. Ответов может быть только три: 30 дней, 31 день или 28 или 29 дней для февраля. Итак, хотя есть 12 месяцев, нам нужно только три пункта.
В этом скрипте пользователю предлагается ввести название месяца. Чтобы сделать сопоставление с образцом нечувствительным к регистру, мы используем команду shop
с параметром -s nocasematch
. Не имеет значения, содержит ли ввод прописные, строчные буквы или их смесь.
#!/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
Февраль получает отдельный пункт, а все остальные месяцы делят два пункта в зависимости от того, 30 или 31 день в них. В предложениях с несколькими шаблонами используется символ вертикальной черты «|». как разделитель. Случай по умолчанию улавливает неправильно написанные месяцы.
Мы сохранили это в файл под названием «month.sh» и сделали его исполняемым.
chmod +x month.sh
Мы запустим скрипт несколько раз и покажем, что не имеет значения, используем ли мы верхний или нижний регистр.
./month.sh
Поскольку мы сказали сценарию игнорировать различия в верхнем и нижнем регистре, любое правильно написанное название месяца обрабатывается одним из трех основных предложений. Плохо написанные месяцы перехватываются предложением по умолчанию.
Использование цифр в операторах case
Мы также можем использовать цифры или числовые переменные в качестве выражения. Этот сценарий просит пользователя ввести число в диапазоне от 1 до 3. Чтобы было понятно, что шаблоны в каждом предложении являются строками, они заключены в двойные кавычки. Несмотря на это, сценарий по-прежнему сопоставляет ввод пользователя с соответствующим предложением.
#!/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
Использование операторов case в циклах for
Оператор case
пытается сопоставить шаблону одно выражение. Если вам нужно обработать много выражений, вы можете поместить оператор case
в цикл for
.
Этот сценарий выполняет команду ls
для получения списка файлов. В цикле for
подстановка файлов, похожая на регулярные выражения, но отличающаяся от нее, применяется к каждому файлу по очереди для извлечения расширения файла. Это хранится в строковой переменной Extension
.
Оператор case
использует переменную Extension
в качестве выражения, которое пытается сопоставить с предложением.
#!/bin/bash for File in $(ls) do # extract the file extension 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
Наш минималистичный скрипт идентификации типа файла работает.
Обработка кодов выхода с операторами case
Программа с хорошим поведением отправит код выхода в оболочку, когда она завершится. Традиционная схема использует нулевое значение кода выхода, чтобы указать на безпроблемное выполнение, и значения, равные одному или нескольким, чтобы указать различные типы ошибок.
Многие программы используют только ноль и единицу. Объединение всех условий ошибки в один код выхода усложняет выявление проблем, но это обычная практика.
Мы создали небольшую программу под названием «go-geek», которая случайным образом возвращала коды выхода, равные нулю или единице. Следующий скрипт вызывает go-geek
. Он получает код выхода с помощью переменной оболочки $?
и использует ее как выражение для инструкции case
.
Реальный сценарий будет выполнять соответствующую обработку в зависимости от успеха или неудачи команды, сгенерировавшей код выхода.
#!/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
в каталог, который не существует, чтобы получить код выхода из единицы, а затем отредактировать свой скрипт на cd
в доступном каталоге, чтобы получить выход код нуля.
Запуск скрипта несколько раз показывает, что различные коды выхода правильно идентифицируются оператором case
.
./return-code.sh
Разборчивость помогает ремонтопригодности
Возвращаться к старым сценариям Bash и выяснять, как они делают то, что делают, особенно если они были написаны кем-то другим, непросто. Изменение функциональности старых скриптов еще сложнее.
Оператор case
дает вам логику ветвления с ясным и простым синтаксисом. Это беспроигрышный вариант.