Аналогичным образом ведут себя функции, расположенные внутри сценария, и сам сценарий, возвращая код завершения. Код, возвращаемый функцией или сценарием, определяется кодом возврата последней команды. Команде exit можно явно указать код возврата, в виде: exit nnn, где nnn -- это код возврата (число в диапазоне 0 - 255).
Когда работа сценария завершается командой exit без параметров, то код возврата сценария определяется кодом возврата последней исполненной командой.
Код возврата последней команды хранится в специальной переменной $?. После исполнения кода функции, переменная $? хранит код завершения последней команды, исполненной в функции. Таким способом в Bash передается "значение, возвращаемое" функцией. После завершения работы сценария, код возврата можно получить, обратившись из командной строки к переменной $?, т.е. это будет код возврата последней команды, исполненной в сценарии.
Пример 6-1. завершение / код завершения
#!/bin/bash
echo hello
echo $? # код возврата = 0, поскольку команда выполнилась успешно.
lskdf # Несуществующая команда.
echo $? # Ненулевой код возврата, поскольку команду выполнить не удалось.
echo
exit 113 # Явное указание кода возврата 113.
# Проверить можно, если набрать в командной строке "echo $?"
# после выполнения этого примера.
# В соответствии с соглашениями, 'exit 0' указывает на успешное завершение,
#+ в то время как ненулевое значение означает ошибку.
Переменная $? особенно полезна, когда необходимо проверить результат исполнения команды (см. Пример 12-27 и Пример 12-13).
Символ !, может выступать как логическое "НЕ" для инверсии кода возврата.
Пример 6-2. Использование символа ! для логической инверсии кода возврата
true # встроенная команда "true".
echo "код возврата команды "true" = $?" # 0
! true
echo "код возврата команды "! true" = $?" # 1
# Обратите внимание: символ "!" от команды необходимо отделять пробелом.
# !true вызовет сообщение об ошибке "command not found"
# Спасибо S.C.
В отдельных случаях коды возврата должны иметь предопределенные значения и не должны задаваться пользователем.
Глава 7. Проверка условий
практически любой язык программирования включает в себя условные операторы, предназначенные для проверки условий, чтобы выбрать тот или иной путь развития событий в зависимости от этих условий. В Bash, для проверки условий, имеется команда test, различного вида скобочные операторы и условный оператор if/then.
7.1. Конструкции проверки условий
Оператор if/then проверяет -- является ли код завершения списка команд 0 (поскольку 0 означает "успех"), и если это так, то выполняет одну, или более, команд, следующие за словом then.
Существует специальная команда -- [ (левая квадратная скобка). Она является синонимом команды test, и является встроенной командой (т.е. более эффективной, в смысле производительности). Эта команда воспринимает свои аргументы как выражение сравнения или как файловую проверку и возвращает код завершения в соответствии с результатами проверки (0 -- истина, 1 -- ложь).
Начиная с версии 2.02, Bash предоставляет в распоряжение программиста конструкцию [[ ... ]] расширенный вариант команды test, которая выполняет сравнение способом более знакомым программистам, пишущим на других языках программирования. Обратите внимание: [[ -- это зарезервированное слово, а не команда.
Bash исполняет [[ $a -lt $b ]] как один элемент, который имеет код возврата.
Круглые скобки (( ... )) и предложение let ... так же возвращают код 0, если результатом арифметического выражения является ненулевое значение. Таким образом, арифметические выражения могут учавствовать в операциях сравнения.
Предложение let "1<2" возвращает 0 (так как результат сравнения "1<2" -- "1", или "истина")
(( 0 && 1 )) возвращает 1 (так как результат операции "0 && 1" -- "0", или "ложь")
Условный оператор if проверяет код завершения любой команды, а не только результат выражения, заключенного в квадратные скобки.
if cmp a b &> /dev/null # Подавление вывода.
then echo "Файлы a и b идентичны."
else echo "Файлы a и b имеют различия."
fi
if grep -q Bash file
then echo "Файл содержит, как минимум, одно слово Bash."
fi
if COMMAND_WHOSE_EXIT_STATUS_IS_0_UNLESS_ERROR_OCCURRED
then echo "Команда выполнена успешно."
else echo "Обнаружена ошибка при выполнении команды."
fi
Оператор if/then допускает наличие вложенных проверок.
if echo "Следующий *if* находится внутри первого *if*."
if [[ $comparison = "integer" ]]
then (( a < b ))
else
[[ $a < $b ]]
fi
then
echo '$a меньше $b'
fi
Это детальное описание конструкции "if-test" любезно предоставлено Stephane Chazelas.
Пример 7-1. Что есть "истина"?
#!/bin/bash
echo
echo "Проверяется "0""
if [ 0 ] # ноль
then
echo "0 -- это истина."
else
echo "0 -- это ложь."
fi # 0 -- это истина.
echo
echo "Проверяется "1""
if [ 1 ] # единица
then
echo "1 -- это истина."
else
echo "1 -- это ложь."
fi # 1 -- это ложь.
echo
echo "Testing "-1""
if [ -1 ] # минус один
then
echo "-1 -- это истина."
else
echo "-1 -- это ложь."
fi # -1 -- это истина.
echo
echo "Проверяется "NULL""
if [ ] # NULL (пустое условие)
then
echo "NULL -- это истина."
else
echo "NULL -- это ложь."
fi # NULL -- это ложь.
echo
echo "Проверяется "xyz""
if [ xyz ] # строка
then
echo "Случайная строка -- это истина."
else
echo "Случайная строка -- это ложь."
fi # Случайная строка -- это истина.
echo
echo "Проверяется "$xyz""
if [ $xyz ] # Проверка, если $xyz это null, но...
# только для неинициализированных переменных.
then
echo "Неинициализированная переменная -- это истина."
else
echo "Неинициализированная переменная -- это ложь."
fi # Неинициализированная переменная -- это ложь.
echo
echo "Проверяется "-n $xyz""
if [ -n "$xyz" ] # Более корректный вариант.
then
echo "Неинициализированная переменная -- это истина."
else
echo "Неинициализированная переменная -- это ложь."
fi # Неинициализированная переменная -- это ложь.
echo
xyz= # Инициализирована пустым значением.
echo "Проверяется "-n $xyz""
if [ -n "$xyz" ]
then
echo "Пустая переменная -- это истина."
else
echo "Пустая переменная -- это ложь."
fi # Пустая переменная -- это ложь.
echo
# Кргда "ложь" истинна?
echo "Проверяется "false""
if [ "false" ] # это обычная строка "false".
then
echo ""false" -- это истина." #+ и она истинна.
else
echo ""false" -- это ложь."
fi # "false" -- это истина.
echo
echo "Проверяется "$false"" # Опять неинициализированная переменная.
if [ "$false" ]
then
echo ""$false" -- это истина."
else
echo ""$false" -- это ложь."
fi # "$false" -- это ложь.
# Теперь мв получили ожидаемый результат.
echo
exit 0
Упражнение. Объясните результаты, полученные в Пример 7-1.