Управляющие структуры
В командной оболочке есть ряд управляющих структур или конструкций, похожих на аналогичные структуры в других языках программирования.
Примечание
В следующих разделах элемент синтаксической записи операторы - это последовательности команд, которые выполняются, когда или пока условие удовлетворяется или пока оно не удовлетворяется.
if
Управляющий оператор if очень прост: он проверяет результат выполнения команды и затем в зависимости отусловия выполняет ту или иную группу операторов.
ifусловие
then
операторы
else
операторы
fi
Наиболее часто оператор if применяется, когда задается вопрос, и решение принимается в зависимости от ответа:
#!/bin/sh
echo "Is it morning? Please answer yes or no "
read timeofday
if [ $timeofday = "yes" ]; then
echo "Good morning"
else
echo "Good afternoon"
fi
exit 0
В результате будет получен следующий вывод на экран:
Is it morning? Please answer yes or no
yes
Good morning
$
В этом сценарии для проверки содержимого переменной timeofday применяется команда [. Результат оценивается оператором командной оболочки if, который затем разрешает выполнять разные строки программного кода.
Примечание
Обратите внимание на дополнительные пробелы, используемые для формирования отступа внутри оператора if. Это делается только для удобства читателя; командная оболочка игнорирует дополнительные пробелы.
elif
К сожалению, с этим простым сценарием связано несколько проблем. Во-первых, он принимает в значении no (нет) любой ответ за исключением yes (да). Можно помешать этому, воспользовавшись конструкцией elif, которая позволяет добавить второе условие, проверяемое при выполнении части else оператора if (упражнение 2.3).
Упражнение 2.3. Выполнение проверок с помощью elif
Вы можете откорректировать предыдущий сценарий так, чтобы он выводил сообщение об ошибке, если пользователь вводит что-либо отличное от yes или no. Для этого замените ветку else веткой elif и добавьте еще одно условие:
#!/bin/sh
echo "Is it morning? Please answer yes or no "
read timeofday
if [ $timeofday = "yes" ]
then
echo "Good morning"
elif [ $timeofday = "no" ]; then
echo "Good afternoon"
else
echo "Sorry, $timeofday not recognized. Enter yes or no "
exit 1
fi
exit 0
Как это работает
Этот пример очень похож на предыдущий, но теперь, если первое условие не равно true, оператор командной оболочки elif проверяет переменную снова. Если обе проверки не удачны, выводится сообщение об ошибке, и сценарий завершается со значением 1, которое в вызывающей программе можно использовать для проверки успешного выполнения сценария.
Проблема, связанная с переменными
Данный сценарий исправляет наиболее очевидный дефект, а более тонкая проблема остается незамеченной. Запустите новый вариант сценария, но вместо ответа на вопрос просто нажмите клавишу <Enter> (или на некоторых клавиатурах клавишу <Return>). Вы получите сообщение об ошибке:
[: =: unary operator expected
Что же не так? Проблема в первой ветви оператора if. Когда проверялась переменная timeofday, она состояла из пустой строки. Следовательно, ветвь оператора if выглядела следующим образом:
if [ = "yes" ]
и не представляла собой верное условие. Во избежание этого следует заключить имя переменной в кавычки:
if [ "$timeofday" = "yes" ]
Теперь проверка с пустой переменной будет корректной:
if [ "" = "yes" ]
Новый сценарий будет таким:
#!/bin/sh
echo "Is it morning? Please answer yes or no "
read timeofday
if [ "$timeofday" = "yes" ]
then
echo "Good morning"
elif [ "$timeofday" = "no" ]; then
echo "Good afternoon"
else
echo "Sorry, $timeofday not recognized. Enter yes or no "
exit 1
fi
exit 0
Этот вариант безопасен, даже если пользователь в ответ на вопрос просто нажмет клавишу <Enter>.
Примечание
Если вы хотите, чтобы команда echo удалила новую строку в конце, наиболее легко переносимый вариант - применить команду printf (см. разд. "printf" далее в этой главе) вместо команды echo. В некоторых командных оболочках применяется команда echo -е, но она поддерживается не всеми системами. В оболочке bash для запрета перехода на новую строку допускается команда echo -n, поэтому, если вы уверены, что вашему сценарию придется трудиться только в оболочке bash, предлагаем вам использовать следующий синтаксис:
echo -n "Is it morning? Please answer yes or no: "
Помните о том, что нужно оставлять дополнительный пробел перед закрывающими кавычками, таким образом формируется зазор перед вводимым пользователем ответом, который в этом случае выглядит четче.
for
Применяйте конструкцию for для обработки в цикле ряда значений, которые могут представлять собой любое множество строк. Строки могут быть просто перечислены в программе или, что бывает чаще, представлять собой результат выполненной командной оболочкой подстановки имен файлов.
Синтаксис этого оператора прост:
forпеременная inзначения
do
операторы
done
Выполните упражнения 2.4 и 2.5.
Упражнение 2.4. Применение цикла for к фиксированным строкам
В командной оболочке значения обычно представлены в виде строк, поэтому можно написать следующий сценарий:
#!/bin/sh
for foo in bar fud 43
do
echo $foo
done
exit 0
В результате будет получен следующий вывод:
bar
fud
43
Примечание
Что произойдет, если вы измените первую строку с for foo in bar fud 43 на for foo in "bar fud 43"? Напоминаем, что вставка кавычек заставляет командную оболочку считать все, что находится между ними, единой строкой. Это один из способов сохранения пробелов в переменной.
Как это работает
В данном примере создается переменная foo и ей в каждом проходе цикла for присваиваются разные значения. Поскольку оболочка считает по умолчанию все переменные строковыми, применять строку 43 так же допустимо, как и строку fud.