Вы можете откорректировать предыдущий сценарий так, чтобы он выводил сообщение об ошибке, если пользователь вводит что-либо отличное от
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
.
Упражнение 2.5. Применение цикла
for
с метасимволами
Как упоминалось ранее, цикл
for
обычно используется в командной оболочке вместе с метасимволами или знаками подстановки для имен файлов. Это означает применение метасимвола для строковых значений и предоставление оболочке возможности подставлять все значения на этапе выполнения.