Выбор команд для выполнения в bash-скрипте можно контролировать с помощью особых блоков кода — управляющих конструкций. К ним относятся условные операторы, циклы и группирующие команды.
В этой статье расскажем, как работать с условными конструкциями для проверки истинности [ … ] и [[ … ]].
Одинарные [ … ] и двойные [[ … ]] квадратные скобки
Одинарные [ … ] и двойные [[ … ]] квадратные скобки — самостоятельные условные конструкции, которые проверяют истинность помещённого в них выражения. Также в них часто помещают тело условия после оператора if. От выбора конструкции зависит форма записи условия — оболочка интерпретирует выражения в одинарных квадратных скобках иначе, чем в двойных.
Конструкция [ … ] — встроенная команда (builtin) оболочки bash. Это форма записи команды test, которая проверяет выполнение условия.
В этой конструкции для аргументов действуют подстановка значений переменных, разделение на слова и поиск по шаблонам (globbing — об этом подробно рассказано в статье Часть 2. Bash-скрипты. Переменные, комментарии, пользовательский ввод). Чтобы спецсимволы внутри одинарных квадратных скобок интерпретировались как операторы (например, =, >, &&, |, ., * и так далее), их нужно экранировать при помощи обратного слэша \ или двойных кавычек "". Внутри конструкции [ … ] нельзя работать с регулярными выражениями и сравнивать строки между собой.
Одинарные скобки используются не только в bash, но и в остальных POSIX-системах.
Пример использования:
file="file name"
[ -f "$file" ] && echo "$file — обычный файл"Так как значение переменной file содержит пробел, внутри конструкции [ … ] имя переменной нужно заключить в кавычки, иначе оболочка интерпретирует значение переменной как два отдельных слова, и возникнет ошибка — указанный файл не будет найден.
Конструкция [[ … ]] — ключевое слово (keyword) оболочки bash. Помещаемые в неё аргументы интерпретируются особым образом — специальные символы не требуется экранировать, а разделение на слова и поиск по шаблонам не работают. Внутри двойных квадратных скобок можно работать с регулярными выражениями и сравнивать строки между собой.
Двойные квадратные скобки менее универсальны, чем одинарные — они предусмотрены в оболочках ksh, zsh и bash, но отсутствуют в sh, ash и dash.
Пример использования:
file="file name"
[[ -f $file ]] && echo "$file — обычный файл"Так как значения переменных внутри конструкции [[ … ]] оболочка не делит на слова, имена переменных в ней не нужно заключать в кавычки.
Выбор оператора сравнения зависит от договорённости в сообществе или предпочтений разработчика. Например, компания Google в своём стиле кода рекомендует использовать в shell-скриптах конструкцию [[ … ]] вместо [ … ], test и /usr/bin/[. По мнению авторов конвенции, это самый надёжный вариант записи: он позволяет избежать ошибок интерпретации, так как не требуется экранирование спецсимволов или иные способы записи операторов (например, -a вместо &&). Кроме того, внутри двойных квадратных скобок можно сравнивать последовательности символов и работать с регулярными выражениями, а конструкция [ … ] не поддерживает эти возможности.
Проверка файлов
В скриптах с оператором if часто проверяют тип и разрешения файлов. Для проверки используют оператор [ ... ] (команды test) и следующие его опции:
| возвращает true (устанавливает, что условие выполнено), если указанный файл существует и является обычным файлом (а не, например, каталогом или символической ссылкой) |
| возвращает true, если указанный файл существует и является каталогом |
| возвращает true, если указанный файл содержит данные (то есть размер файла больше нуля) |
| возвращает true, если указанный файл доступен для чтения |
| возвращает true, если указанный файл доступен для записи |
| возвращает true, если указанный файл является исполняемым файлом |
Пример проверки исполняемости файла:
#!/bin/bash
if [ -x script.sh ]; then
echo 'script.sh можно запустить на исполнение'
else
echo 'script.sh нельзя запустить на исполнение'
fiЭтот скрипт проверяет, может ли действующий пользователь запустить файл на исполнение — установлен ли для него бит исполнения x. Если этот бит присутствует, скрипт возвращает значение true, и выводится сообщение: script.sh можно запустить на исполнение. Если отсутствует — сообщение: script.sh нельзя запустить на исполнение.
Сравнение строк
Две строки равны, если они содержат одну и ту же последовательность символов. В скриптах с оператором if часто проверяют строки на равенство. Для этого используют оператор [ ... ] со следующими операторами:
| Возвращает true, если операнды (сущности, участвующие в операции) равны. Особенности использования операторов = и == с операторами [ ... ] и [[ ... ]] С одинарными квадратными скобками:
С двойными квадратными скобками:
|
string1 != string2 | Возвращает true, если операнды не равны. |
string1 > string2 | Возвращает true, если правый операнд располагается первым при сортировке в алфавитном порядке:
|
string1 < string2 | Возвращает true, если левый операнд располагается первым при сортировке в алфавитном порядке.
|
-z string | Возвращает true, если длина строки равна нулю. |
-n string | Возвращает true, если длина строки не равна нулю. |
-v string | Возвращает true, если назначена переменная с таким именем. |
"string" =~ regular_expression | Возвращает true, если строка соответствует регулярному выражению:
|
Следующий скрипт проверяет, запущен ли определённый сервис, которым управляет systemctl — подсистема инициализации и управления службами во многих дистрибутивах Linux:
#!/bin/bash
echo "Введите название сервиса: "
read service_name
status=$(systemctl is-active $service_name)
if [ "$status" = "active" ]; then
echo "Сервис $service_name запущен."
else
echo "Сервис $service_name не запущен."
fi- Пользователю предлагают ввести имя одного из системных сервисов Linux.
- Введённое значение подставляется в команду
systemctl, которая проверяет состояние сервиса с указанным названием. Результат выполнения командыsystemctlсохраняется в переменнуюstatus. - Если значение переменной —
active, отображается сообщение о том, что сервис запущен. - Во всех прочих сценариях (включая случай, когда сервис не установлен в системе) отображается сообщение о том, что сервис не запущен.
Сравнение чисел
Для сравнения чисел используют оператор [ ... ] и следующие операторы:
-eq | равно (equal) |
-ne | не равно (not equal) |
-gt | больше (greater than) |
-lt | меньше (less than) |
-ge | больше или равно (greater or equal) |
-le | меньше или равно (less or equal) |
Эти операторы работают только с целыми числами.
В следующем скрипте используется утилита sensors для измерения температуры ЦП. Она входит в пакет lm-sensors, который отслеживает значения параметров аппаратного обеспечения компьютера.
Команда установки пакета lm-sensors для операционных систем семейств Ubuntu и Debian:
sudo apt install lm-sensorsДля систем CentOS и RHEL:
sudo yum install lm-sensorsСкрипт проверяет текущую температуру одного из ядер процессора — Core 0:
#!/bin/bash
current_temp=$(sensors | grep "Core 0" | awk '{print $3}' | sed 's/+//; s/°C//' | head -n 1)
current_temp_int=$(bc <<< "${current_temp}/1")
threshold=80
if [ "$current_temp_int" -gt "$threshold" ]; then
echo "Внимание: высокая температура! Текущая температура: ${current_temp}°C."
else
echo "Температура нормальная. Текущая температура: ${current_temp}°C."
fiСкрипт выполняет следующие действия:
- В переменную
current_tempзаписывается вывод конвейера из следующих команд:- Вывод команды
sensorsпередаётся командеgrepдля поиска строки (или строк) с фрагментомCore 0. - Вывод
grepпередаётся команде для обработки текстаawk, которая находит третье поле полученной строки и выводит его. - Вывод
awkпередаётся командеsed, которая удаляет символ+перед значением температуры и°Cпосле него. - Так как процессоров с ядром
Core 0может быть несколько, утилитаheadоставляет только первую из обработанных строк с фрагментомCore 0.
- Вывод команды
- Так как операторы сравнения чисел работают только с целыми числами, а программа
sensorsвыводит значения температуры с плавающей точкой, значение переменнойcurrent_tempпреобразуется в целое: делится на единицу и передаётся в виде here-строки программе-калькуляторуbc, а затем в преобразованном виде записывается в переменнуюcurrent_temp_int. - Переменной
thresholdприсваивается значение 80. Команда
echoвыводит результат сравнения значений переменныхcurrent_temp_intиthreshold.Таким образом скрипт проверяет: значение переменной
current_temp_intбольше значения переменнойthreshold?Если да, то выводится сообщение:
Внимание: повышенная температура! Текущая температура — <значение переменной $current_temp>.
Если нет, то выводится сообщение:
Температура нормальная. Текущая температура — <значение переменной $current_temp>.

Мы рассмотрели условные конструкции в языке bash: узнали, как работать с одинарными [ … ] и двойными [[ … ]] квадратными скобками, которые в bash-скриптах позволяют проверять выполнение условий для разных типов данных.
Во второй части статьи расскажем, как работать с операторами if и case, а также с логическими операторами && и ||.
Автор статьи: Клара Суботэ