Шрифт:
27. Управление потоком выполнения: ветвление при помощи if
В предыдущей главе мы столкнулись с проблемой. Как помочь сценарию адаптировать свое поведение в зависимости от привилегий пользователя, запустившего его? Для решения проблемы нам необходим некий способ «изменить направление» выполнения сценария, опираясь на результаты проверки. Выражаясь языком программистов, нам нужен способ, обеспечивающий ветвление программы.
Рассмотрим простой пример логики, выраженный в псевдокоде, имитирующем язык компьютеров, но понятном человеку:
x = 5
Если x = 5, тогда:
Сказать «x равно 5».
Иначе:
Сказать «x не равно 5».
Это — пример ветвления. Если условие «x = 5?» верно, выполняется строка: «Сказать ‘x равно 5’». Иначе выполняется строка: «Сказать ‘x не равно 5’».
Использование if
В сценариях на языке командной оболочки описанную выше логику можно реализовать так:
x=5
if [ $x = 5 ]; then
echo "x equals 5."
else
echo "x does not equal 5."
fi
А если то же самое можно выполнить непосредственно в командной строке, получается немного короче:
[me@linuxbox ~]$ x=5
[me@linuxbox ~]$ if [ $x = 5 ]; then echo "equals 5"; else echo "does not equal 5"; fi
equals 5
[me@linuxbox ~]$ x=0
[me@linuxbox ~]$ if [ $x = 5 ]; then echo "equals 5"; else echo "does not equal 5"; fi
does not equal 5
В этом примере мы выполнили команду дважды. Первый раз со значением 5 в переменной x, что привело к выводу строки equals 5, и второй раз со значением 0 в переменной x, что привело к выводу строки not equal 5.
Инструкция if имеет следующий синтаксис:
if команды; then
команды
[elif команды; then
commands...]
[else
команды]
fi
где команды — это список команд. На первый взгляд такой синтаксис выглядит запутанным. Но прежде чем прояснить его, посмотрим, как командная оболочка определяет, успешно или нет выполнена команда.
Код завершения
Команды (включая сценарии и функции, написанные нашими собственными руками) по завершении работы возвращают системе значение, которое называют кодом завершения (exit status). Это значение — целое число в диапазоне от 0 до 255 — сообщает об успешном или неуспешном завершении команды. По соглашениям значение 0 служит признаком успешного завершения, а любое другое — неуспешного. Командная оболочка поддерживает переменную, посредством которой можно определить код завершения. Например:
[me@linuxbox ~]$ ls -d /usr/bin
/usr/bin
[me@linuxbox ~]$ echo $?
0
[me@linuxbox ~]$ ls -d /bin/usr
ls: cannot access /bin/usr: No such file or directory
[me@linuxbox ~]$ echo $?
2
В этом примере мы дважды выполнили команду ls. В первый раз команда выполнилась благополучно. Если вывести значение переменной $?, можно увидеть, что оно равно 0. Во второй раз команда ls сообщила об ошибке, а переменная $? содержала значение 2, указывающее, что команда столкнулась с ошибкой. Одни команды используют разные коды завершения, чтобы сообщить о характере ошибки, тогда как другие, столкнувшись с любой ошибкой, просто возвращают значение 1. Страницы справочного руководства часто включают раздел с заголовком «Exit Status» («Коды завершения»), описывающий возвращаемые коды. Однако 0 всегда служит признаком успешного выполнения.
Командной оболочкой поддерживаются две чрезвычайно простые встроенные команды, которые просто завершаются с кодом 0 или 1. Команда true всегда завершается с признаком успеха, а команда false — всегда с признаком ошибки:
[me@linuxbox ~]$ true
[me@linuxbox ~]$ echo $?
0
[me@linuxbox ~]$ false
[me@linuxbox ~]$ echo $?
1
Эти команды можно использовать для исследования особенностей работы инструкции if. Инструкция if в действительности просто оценивает код завершения команды:
[me@linuxbox ~]$ if true; then echo "It's true."; fi
It's true.
[me@linuxbox ~]$ if false; then echo "It's true."; fi
[me@linuxbox ~]$
Команда echo "It's true." выполняется, только если команда, следующая за if, завершается успешно, и не выполняется, если команда, следующая за if, завершается с признаком ошибки. Если за if следует список команд, успешность выполнения всего списка определяется по последней команде:
[me@linuxbox ~]$ if false; true; then echo "It's true."; fi