Текст книги "Linux и UNIX: программирование в shell. Руководство разработчика"
Автор книги: Дэвид Тейнсли
сообщить о нарушении
Текущая страница: 13 (всего у книги 25 страниц)
$ expr 30 *.3
90
17.5.1. Приращение переменной цикла
Команда expr выполняет приращение переменной цикла. Сначала переменной цикла присваивается начальное значение нуль. Затем добавляется единица. Кавычки применяются для обозначения подстановки команд. Выводимые данные, полученные с помощью команды expr, присваиваются переменной цикла.
$ loop=0
$ LOOP=`expr $LOOP + 1`
17.5.2. Проверка численных значений
Команду expr можно применять для выполнения сравнений чисел. Если вычисления выполняются с числами, отличными от целых, отображается сообщение об ошибке, например:
$ expr rr + 1
expr: нечисловой аргумент
Итак, необходимо передать значение переменной (не важно, какой именно), выполнить любую арифметическую операцию и направить выводимые данные в /dev/null. Затем достаточно проверить код завершения последней команды. Если код равен нулю, тогда мы имеем дело с числом; любое другое значение свидетельствует о том, что данное значение не является числом.
$ VALUE=12
$ expr $VALUE + 10 > /dev/null 2>&1
$ echo $?
0
Это – число.
$ VALUE=hello
$ expr $VALUE + 10 > /dev/null 2>&1
$ echo $?
2
А это – не численное значение.
Команда expr также возвращает свой собственный код завершения. К сожалению, значение этого кода противоположно значению кода завершения последней команды. Команда expr отображает единицу, если результат проверки истинен, и любое другое значение, если допущена какая‑либо неточность или ошибка. Ниже приводится пример проверки двух строк на предмет равенства. В ходе проверки требуется выяснить, является ли строка "hello" равной строке "hello".
$ VALUE=hello
$ expr $VALUE="hello"
1
$ echo $?
0
Команда expr возвращает единицу. Не беспокойтесь, все идет хорошо. Теперь выполним проверку с помощью кода завершения последней команды: возвращается значение нуль. В ходе проверки выяснилось, что строка "hello" действительно равна строке "hello".
17.5.3. Поиск по шаблону
С помощью команды expr можно реализовать поиск по шаблону. Подсчет количества символов строки возможен с помощью команды expr. При этом нужно дополнительно указать опцию после двоеточия. Комбинация '. *' означает, что в кавычках может указываться любое количество произвольных символов.
$ VALUE=accounts.doc
$ expr $VALUE : October 8, '.*'
12
Команду expr можно также использовать при поиске совпадающих строк; ниже показано, как применяется шаблон ".doc" для извлечения оставшейся части имени файла.
$ expr $VALUE : '(.*).doc'
accounts
17.6. Заключение
В настоящей главе рассматриваются основные возможности команд test и expr. Показано, как проверяются права доступа к файлу, как тестируются строки. С помощью других условных операторов, типа "if then else" и "case", можно реализовать всестороннюю проверку. Подобный подход позволяет предпринимать определенные действия по результатам проверки.
ГЛАВА 18
Управляющие конструкции
Все функциональные сценарии должны предлагать возможности по выбору возможных вариантов. При определенных условиях сценарии должны выполнять обработку списков. Этим вопросам посвящена настоящая глава. Кроме того, в ней описывается создание и реализация управляющих конструкций в сценариях. Вот перечень тем, обсуждаемых в данной главе:
• коды завершения;
• циклы while, for и until;
• операторы if then else;
• принятие решений в сценариях;
• создание меню.
18.1. Коды завершения
Перед тем как рассмотреть некоторые примеры удачных сценариев, посвятим несколько слов кодам завершения. Каждая выполняемая команда возвращает код завершения. Чтобы просмотреть его, достаточно воспользоваться кодом завершения последней команды:
$ echo $?
Существует четыре основных типа кодов завершения. Два из них уже упоминались, а именно: код завершения последней команды $? и команды, изменяющие ход выполнения сценария (&&,||). Две оставшиеся разновидности команд имеют отношение к завершению shell–сценария или интерпретатора shell, а также связаны с кодом завершения или кодами возврата функции. Эти коды рассматриваются в главе 19, посвященной изучению функций.
Для завершения текущего процесса в интерпретаторе shell используется команда exit. Общий формат команды:
exit n
где n – числовое значение.
Чтобы завершить работу с интерпретатором shell, не создавая во время текущего сеанса другой интерпретатор shell, достаточно в командной строке ввести команду exit. Если указать команду exit без параметров, интерпретатор shell будет отображать (и отображает) значение последней команды. Существует большое количество
значений кода выхода. Но чаще всего при работе со сценариями и общими системными командами используются два значения кода выхода:
Код завершения 0 Успешное завершение, ошибок нет Код завершения 1 Неудачное завершение, имеется ошибка
В shell–сценариях можно реализовать пользовательские коды завершения для выхода из сценария. Желательно, чтобы пользователь чаще применял эту возможность. Какой‑либо иной shell–сценарий или функция, возвращающая результат, могут использовать код завершения вашего сценария. Кроме того, завершение сценария с генерацией кода завершения свидетельствует о культуре программирования. Выполнение сценария обычно завершается после того, как пользователь неправильно вводит данные, если не удается обнаружить ошибку, а также после окончания обычного процесса обработки.
Примечание:
Начиная с этого места книги, все сценарии включают строки комментария. Строки комментария содержат разъяснения, которые помогают запомнить или ясно представить выполнение сценариев. Поскольку интерпретатор команд игнорирует строки комментария, можно располагать их по своему усмотрению. Строка комментария должна начинаться символом #.
18.2. Управляющие конструкции
Почти все сценарии, за редким исключением, обладают свойством самоуправляемости. В чем состоит управление ходом выполнения сценария? Предположим, что в состав сценария включено несколько команд:
#!/bin/sh
# создание каталога
mkdir /home/dave/mydocs
# копирование всех файлов с расширением doc
cp *.docs /home/dave/docs
# удаление всех файлов с расширением doc
rm *.docs
Рассматриваемый сценарий выполняет определенные задачи. Каковы же могут быть причины возможных неприятностей? Проблема возникнет, например, в том случае, если нельзя будет создать данный каталог. Как поступить в иной ситуации, если каталог может быть создан, но при копировании файлов появляется сообщение об ошибке? Что произойдет, если применить команду cp к разным файлам из различных каталогов. Продуманные решения нужно принимать до применения команды, а еще лучше, если они реализуются при получении результатов выполнения последней команды. Интерпретатор shell приходит здесь на помощь, поддерживая наборы командных операторов, которые помогают принять верное решение в зависимости от успеха или неудачи при выполнении команды либо при обработке списка. Существует два вида таких командных операторов:
• операторы цикла;
• операторы, изменяющие ход выполнения сценария.
18.2.1. Операторы, изменяющие ход выполнения сценария
Операторы if, then, else позволяют реализовать условное тестирование. Проверить условия можно самыми различными способами. Например, может производиться оценка размера файла, проверка установленных прав доступа к файлу, сравнение каких‑либо числовых значений или строк. В результате выполнения сравнений возвращается значение "истина" (0) либо "ложь" (1), и затем предпринимаются действия на основании полученного результата. Перед тем как мы приступим к обсуждению условного тестирования, стоит отметить, что некоторые понятия из этой области были рассмотрены ранее.
Операторы case дают возможность выполнять поиск по шаблонам, словам или числовым значениям. После нахождения нужного шаблона или слова можно переходить к выполнению других операторов, которые основываются исключительно на условии, по которому устанавливалось соответствие.
18.2.2. Циклические операторы
Цикл, или итерация, – это процесс повторного выполнения наборов команд. В распоряжении пользователя имеется три вида операторов цикла:
for loop
Последовательная обработка значений до тех пор, пока не встретится окончание списка
until loop
Используется реже всего. Оператор определяет непрерывное выполнение цикла, пока условие не станет истинным. Проверка условия выполняется в конце цикла
while loop
Задает выполнение цикла до тех пор, пока не будет встречено заданное условие. Проверка условия выполняется в начале цикла
Каждый цикл, содержащий операторы управления ходом выполнения сценария, может быть вложен. Например, внутри цикла for loop может размещаться другой цикл for loop.
После ознакомления с циклами и процессом управления ходом выполнения сценария рассмотрим некоторые сценарии.
С этого момента все операторы echo в сценариях имеют отношение к Linux или UNIX BSD. То есть при выводе на экран используется метод "echo -e -n", при котором не выполняется создание новой строки в конце вывода. В главе 19 будет показано» как можно воспользоваться универсальной командой echo, которая выполняется для обеих разновидностей системы UNIX (System V и BSD).
18.3. Операторы if then else
Оператор if позволяет осуществить проверку условий. Проверка выполняется на основе значений «истина» (0) или «ложь» (1), после чего могут вызываться наборы операторов. Конструкция оператора if идеально подходит для проверки ошибок. Этот оператор имеет следующий формат:
if условие1
then
команды1
elif условие2
then
команды2
else
командыЗ
fi
Рассмотрим подробно, какие действия выполняются при вызове оператора if.
if условие1
если условие1 истинно
than
тогда
команды1
выполняйте команды1
elif условие2
если условие1 ложно
then
тогда
команды2
выполняйте команды2
else
если условие1 или условие2 не выполняется
командыЗ
тогда выполняйте командыЗ
fi
конец
Оператор if обязательно завершается ключевым словом fi. Довольно распространенной ошибкой является пропуск слова f i при закрытии оператора if. Следует отметить, что подобную ошибку могут допускать даже опытные программисты.
Ключевые слова elif и else использовать необязательно. Если оператор не содержит ключевое слово elif, то можно не указывать и else. Оператор if может также включать несколько блоков, начинающихся ключевым словом elif. Основной конструкцией оператора if является конструкция if then fi.
А теперь рассмотрим несколько примеров.
18.3.1. Простые операторы if
Базовая структура оператора if выглядит следующим образом:
if условие
then команды
fi
При использовании оператора if команды ветви then следует указывать в новой строке; если это правило нарушается, отображается сообщение об ошибке. По поводу применения разделителя команд нет единого мнения. Ниже указан разделитель, который будет применяться далее в книге. Простой оператор if в этом случае приобретает вид:
if условие; then
команды fi
Обратите внимание на отступы. Делать их необязательно, но использование отступов значительно облегчает просмотр сценария и понимание хода проверки условий и выполнения операций.
В следующем примере тестовый оператор используется для проверки того, меньше ли число "10" числа "12". Конечно, это условие истинно, и поэтому выполняются операторы, следующие за частью then; в данном случае, на экран просто выводится соответствующее утверждение. Если условие ложно, сценарий завершается, поскольку этот оператор не содержит части else.
$ pg iftest
#!/bin/sh
#iftest
#это строка комментария, все строки комментария начинаются символом # if [ "10" – lt "12" ]
then
# да, 10 меньше 12
echo "Yes, 10 ls less than 12"
fi
18.3.2. Проверка значений переменных
Чтобы узнать, задал ли пользователь информацию, можно проверить переменную, которая используется для просмотра вводных данных. Ниже приведены результаты проверки того, присвоены ли какие‑либо данные переменной name после нажатия пользователем клавиши ввода.
$ pg iftest2
#!/bin/sh
# если test2
echo -n "Enter your name :"
read NAME
# правильно ли пользователь ввел данные ????
if [ "$NAME"="" ] ; then
echo "You did not enter any information" fi
$ iftest2
Enter your name :
You did not enter any information
18.3.3. Проверка вывода команды grep
Кроме проверки значений переменных или чисел вы можете, к примеру, определить, успешно ли выполнена системная команда.
Чтобы выяснить, была ли выполнена команда grep, можно применить оператор if. В приведенном ниже примере команда grep используется для уточнения, содержится ли в файле data.file слово "Dave". Обратите внимание на то, что при поиске соответствия используется шаблон "Dave>".
$ pg grepif
#!/bin/sh
# grepif
if grep 'Dave>' data.file > /dev/null 2>&l
then
echo "Great Dave ls in the file" else
echo "No Dave ls not in the file"
fi
$ grepif
No Dave is not in the file
В примере вывод команды grep направляется в системную корзину. Если поиск значения, совпадающего с шаблоном, завершился удачно, команда grep возвращает
значение 0. В этом случае происходит (естественная интеграция с оператором if; если команда grep успешно завершилась, часть if принимает значение "истина".
18.3.4. Проверка вывода команды grep с помощью переменной
Как уже упоминалось, команду grep можно применять в строке. В следующем сценарии пользователь вводит список имен; затем команда grep ищет переменную, которой присвоено имя некого лица (Peter).
$ pg grepstr
#!/bin/sh
# grepstr
echo -n "Enter a list of names:"
read list
if echo $1ist | grep "Peter" > /dev/null 2>&1
then
echo "Peter ls here"
# можно ли выполнить обработку здесь
else
echo "Peter's not in the list. No comment!"
fi
Ниже приводятся результаты вывода, где содержится несколько имен.
$ grepstr
Enter a list of names:John Louise Peter James
Peter is here
18.3.5. Проверка результата копирования файла
А теперь осуществим проверку того, успешно ли прошло копирование файла. Если команда cp не скопировала файл myfile в файл myfile.bak, отображается сообщение об ошибке. Обратите внимание, что в сообщении об ошибке фигурирует команда `basename $0` которая выводит на экран название сценария.
Если все сценарии завершаются ошибкой, желательно, чтобы наряду с указанием на стандартную ошибку отображалось и название сценария. В конце концов, пользователю важно знать название сценария, выполнение которого привело к появлению ошибки.
$ pg ifcp
#!/bin/sh
# ifcp
if cp myfile myfile.bak; then
echo "good copy"
else
echo "`basename $0`: error could not copy the files" >&2 fi
$ ifcp
cp: myfile: No such file or directory
ifcp: error could not copy the files
Обратите внимание на то, что в данном случае файл не может быть найден, и генерируется системное сообщение об ошибке. Ошибки такого типа могут негативно
отразиться на выводимых данных; сценарий уже отображает сообщения об ошибках, поэтому известно, что он функционирует неверно. Зачем же нам повторное уведомление? Чтобы избавиться от ошибок, генерируемых системой, и системных данных вывода, достаточно применить перенаправление стандартного потока ошибок и потока вывода. Для этого немного перепишем сценарий: > /dev/null 2>&1. В этом случае получим следующее:
$ pg ifcp
#!/bin/sh
# ifcp
if cp myfile myfile.bak >/dev/null 2>&1; then
echo "good copy"
else
echo "`basename $0`: error could not copy the files" >&2
fi
При выполнении сценария все выводимые данные, включая ошибки, направляются в системную корзину.
$ ifcp
ifcp: error could not copy the files
18.3.6. Проверка текущего каталога
Некоторые сценарии, реализующие административные задачи, можно выполнять из корневого каталога. Если производится глобальное перемещение файлов или же изменяются права доступа к файлу, несложный тест позволяет уточнить, вовлекается ли в этот процесс корневой каталог. В следующем сценарии для хранения текущего каталога переменная DIRECTORY использует подстановку команд. Затем значение этой переменой сравнивается со строкой, содержащей значение "/" (которое и соответствует корневому каталогу). Если значение переменной directory не идентично этой строке, пользователь завершает работу со сценарием. В этом случае код завершения будет 1, что свидетельствует о наличии ошибки.
$ pg ifpwd
#!/bin/sh
# ifpwd DIRECTORY=`pwd`
# захват текущего каталога
if [ "$DIRECTORY" != "/" ]; then
#это корневой каталог ?
#нет, перенаправление вывода в стандартный поток ошибок, который
#отображается на экране по умолчанию.
echo "You need to be in the root directory not $DIRECTORY to run this script" >&2
# выход из сценария со значением 1, ошибка
exit 1
fi
18.3.7. Проверка прав доступа к файлу
Вы можете также осуществлять контроль прав доступа к файлу. Ниже приводится несложная проверка на предмет того, можно ли вести записи в файле test.txt, который переприсвоен переменной logfile.
$ pg ifwr
#!/bin/sh
# ifwr
LOGFILE=test.txt echo $LOGFILE
if [ ! —w "$LOGFILE" ]; then
echo " You cannot write to $LOGFILE " >&2
fi
18.3.8. Проверка параметров, передаваемых сценарию
Оператор if может применяться при определении числа параметров, которые передаются сценарию. Чтобы проверить, соответствует ли количество необходимых параметров количеству вызываемых параметров, используется специальная переменная $#, содержащая число вызываемых параметров.
В приведенном ниже примере проверяется наличие трех параметров; если они отсутствуют, на экран выводится сообщение из стандартного потока ошибок. Затем сценарий завершается, отображая статус ошибки. Если же количество параметров равно трем, все аргументы выводятся на экран.
$ pg ifparam
#!/bin/sh
# ifparam
if [ $# -lt 3 ] ; then
#вызывается меньше, чем 3 параметра, на экран выводится сообщение, затем
#прерывается выполнение сценария
echo "Usage: `basename $0` arg1 arg2 arg3" >&2
exit 1
fi
# хорошо, получено 3 параметра, отображаются на экране
echo "arg1: $1"
echo "arg2: $2"
echo "arg3: $3"
Если передается только два параметра, на экран выводится соответствующее сообщение, и сценарий прекращает выполняться:
$ ifparam cup medal
Usage:ifparam argl arg2 arg3
При передаче трех параметров происходит следующее:
$ ifparam cup medal trophy
argl: cup arg2: medal arg3: trophy
18.3.9. Определение интерактивного режима выполнения сценария
Иногда требуется выяснить, выполняется сценарий в интерактивном режиме (режим терминала( либо не в интерактивном режиме (команды cron или at). Такая информация необходима для того, чтобы сценарий мог определить, где можно получить вводимые данные и куда направлять выводимые данные. Чтобы уточнить режим выполнения сценария, достаточно воспользоваться командой test с опцией -t. Если возвращается значение "истина", сценарий выполняется в интерактивном режиме.
$ pg ifinteractive
#! /bin/sh
# ifinteractive
if [ -t ]; then
echo "We are interactive with a terminal"
else
echo "We must be running from some background process probably cron or at " fi
18.3.10. Простые операторы if else
Следующая форма оператора if применяется чаще всего:
if условие
then команды1
else
команды2
fi
Если условие не удовлетворяет тестированию, часть else оператора if позволяет перейти к соответствующей операции.
18.3.11. Проверка установок переменных
Ниже проверяется установка переменной среды editor. Если переменной EDITOR не присвоено значение, пользователь информируется о том, что переменная editor не установлена. Если переменная editor установлена, тип редактора отображается на экране:
$ рg ifeditor
#!/bin/sh
# ifeditor
if [ -z $EDITOR ]; then
#переменная не установлена
echo "Your EDITOR environment is not set"
else
#посмотрим, что же это
echo "Using $EDITOR as the default editor"
18.3.12. Проверка пользователя, выполняющего сценарий
В следующем примере для проверки условия используется переменная среды. Здесь проверяется, присвоено ли переменной LOGNAME значение "root". Обычно этот тип оператора добавляется в начале сценариев в качестве дополнительной меры безопасности. Несомненно, переменная LOGNAME может проверяться для каждого действительного пользователя.
Если значение переменной не равно строке "root", на экран выводится сообщение из стандартного потока ошибок. Пользователь информируется о том, что он не является пользователем root, а сценарий завершается со значением ошибки, равным 1.
Если строка "root" равна значению переменной LOGNAME, выполняется оператор, который находится после else.
На практике в этом случае сценарий продолжает обработку задания в обычном режиме. Соответствующие операторы находятся после конструкции fi, поскольку все пользователи, отличные от пользователя root, лишаются доступа к сценарию еще на первом этапе проверки.
$ pg ifroot
#!/bin/sh
# ifroot
if [ "$LOGNAME" != "root" ]
# если пользователь не является пользователем root
echo "You need to be root to run this script" >&2
exit 1
else
# да, это пользователь root
echo "Yes indeed you are $LOGNAME proceed"
fi
# выполнение операторов в обычном режиме
18.3.13. Передача параметров сценария системной команде
Позиционные параметры можно передать сценарию, а затем проверить значение переменной. Если при этом пользователь указывает после названия сценария наименование каталога, сценарий заново присваивает специальному параметру $1 более содержательное название, в данном случае directory. С помощью команды ls -A проверяется, не является ли каталог пустым. Если каталог пуст, эта команда не возвращает данные. Затем отображается соответствующее сообщение.
$ pg ifdirec
#!/bin/sh
#ifdirec
#присваивание $1 переменной DIRECTORY DIRECTORY=$1
if [ "`ls -A $DIRECTORY/`"="" ] ; then
# если строка пуста, каталог пуст
echo "$DIRECTORY is indeed empty" else
# в противном случае, нет
echo "$DIRECTORY” is not empty"
fi
Вместо указанного метода можно воспользоваться другой возможностью. Получим аналогичный результат.
$ pg ifdirec2
#!/bin/sh
# ifdirec2
DIRECTORY=$1
if [ -z "`ls -A $DIRECTORY`" ] then
echo "$DIRECTORY is indeed empty" else
echo "$DIRECTORY is not empty"
fi
18.3.14. Применение команды null
Обычно при проведении проверки условий выполняются части then и else. Иногда независимо от того, истинно или ложно условие, нет необходимости переходить к действиям.
К сожалению, нельзя оставлять незаполненными части оператора if – здесь должен находиться какой‑либо оператор. Чтобы разрешить это затруднение, интерпретатор shell поддерживает команду null ':'. Команда null всегда возвращает значение "истина", что в данном случае нас удовлетворяет. Возвращаясь к предыдущему примеру, заметим, что если каталог пуст, команды можно размещать только в части then.
$ pg ifdirectory
#!/bin/sh
# ifdirectory
DIRECTORY=$1
if [ "`ls -A $DIRECTORY`"="" ]
then
echo "$DIRECTORY is indeed empty"
else : # не выполняет ничего
fi
18.3.15. Проверка на предмет создания каталога
В продолжение темы каталогов рассмотрим следующий сценарий. Сценарий получает параметр и пытается создать каталог при помощи значения этого параметра. Параметр передается на командную строку и заново присваивается переменной под названием directory. В данном случае проверяется, является ли переменная нулем.
if [ "$DIRECTORY" = "" ]
Вместо предложенного варианта можно воспользоваться общим случаем проверки параметров:
if [ $# -lt 1 ]
Если строка нулевая, отображается соответствующее сообщение и сценарий завершается. Если каталог уже имеется, никаких дополнительных действий не предпринимается и сценарий выполняется далее.
Пользователь получает запрос, действительно ли нужно создавать каталог. Если он вводит символ, отличный от Y или у, выполняется команда null, в результате чего не предпринимается никаких действий. Каталог создан.
Чтобы проверить, создан ли каталог, применяется код завершения последней команды. Если каталог не был создан, отображается соответствующее сообщение.
$ pg ifmkdir
#!/bin/sh
#ifmkdir
#параметр передается как $1, но заново присваивается переменной DIRECTORY DIRECTORY=$1
#является ли строка пустой ??
if [ "$DIRECTORY"="" ]
then
echo "Usage: `basename $0` directory to create" >&2
exit 1
fi
if [ -d $DIRECTORY ] then :
# ничего не выполняет
else
echo "The directory does exist"
echo -n "Create it now? [y..n] :"
read ANS
if [ "$ANS"="y" ] || [ "$ANS"="Y" ]
then
echo "creating now"
# создайте каталог и перешлите все данные вывода в /dev/null mkdir $DIRECTORY >/dev/null 2>&1 if [ $? != 0 ]; then
echo "Errors creating the directory $DIRECTORY" >&2
exit 1
fi
else :
# ничего не выполняет
fi
При выполнении указанного сценария получим следующее:
$ ifmkdir dt
The directory does exist Create it now? [y..n]: у
creating now
18.3.16. Другие возможности копирования
С помощью команды cp сценарию передается два параметра (они должны содержать имена файлов). Затем системная команда cp копирует значение параметра $1 в параметр $2, а поток вывода перенаправляется в /dev/null. Если команда выполнилась успешно, никаких действий не предпринимается, т. е. применяется команда null.
С другой стороны, если в процессе выполнения команды произошел сбой, об этом следует узнать до завершения сценария.
$ pg ifcp2
#!/bin/sh
#ifcp2
if cp $1 $2 > /dev/null 2>&1
# успешно, ничего делать не надо
then :
else
# плохо, покажем пользователю, какие файлы здесь были.
echo "`'basename $0`: ERROR failed to copy $1 to $2"
exit 1
fi
Выполнение сценария при отсутствии ошибки, связанной с командой ср:
$ ifср2 myfile.lex myfile.lex.bak
Сценарий выполняется при наличии ошибок в команде ср:
$ ifcp2 myfile.lexx myfile.lex.bak
ifcp2: ERROR failed to copy myfile.lexx myfile.lex.bak
В следующем примере для сортировки файла под именем accounts.qtr применяется команда sort.
Результаты вывода направляются в системную корзину. Но кому интересно видеть на экране 300 отсортированных строк? Если сортировка прошла успешно, не нужно предпринимать никаких действий; если при выполнении команды имелись сбои, следует сообщить об этом пользователю.
$ pg ifsort
#!/bin/sh
# ifsort
if sort accounts.qtr > /dev/null
# отсортировано. Прекрасно
then :
else
# лучше сообщим об этом пользователю
echo "`basename $0`: Oops..errors could not sort accounts.qtr"
18.3.17. Применение нескольких операторов if
Операторы if можно вкладывать; при этом нужно следить, чтобы каждому ключевому слову if соответствовало слово fi.
18.3.18. Проверка и установка переменных среды
В предыдущих разделах к переменной среды editor обращались, чтобы узнать, установлена ли она. Сделаем шаг вперед и уточним, не была ли переменная среды установлена ранее. Ниже приводится соответствующий сценарий.
$ pg ifseted
#!/bin/sh
#ifseted
#установлена ли переменная EDITOR ?
if [ -z $EDITOR ] ; then
echo "Your EDITOR environment ls not set"
echo "2 will assume you want to use vi..OK"
echo -n "Do you wish to change it now? [y..n] :"
read ANS
# проверка верхнего или нижнего регистра для 'у'
if [ "$ANS"="у" ] || [ "$ANS"="Y" ]; then
echo "enter your editor type :"
read EDITOR
if [ -z $EDITOR ] || [ "$EDITOR"="" ]; then
#если переменная EDITOR не установлена, ей не присвоено значение,
#тогда присвоим ей значение vi
echo "No, editor entered, using vi as default"
EDITOR=vi; export EDITOR
fi
# берется значение и присваивается переменной EDITOR
EDITOR=$EDITOR
export EDITOR
echo "setting $EDITOR"
fi
else
# пользователь
echo "Using vi as the default editor"
EDITOR=vi; export EDITOR
fi
Рассмотрим, как работает приведенный сценарий. Сначала проверим, установлена ли эта переменная. Если это так, появляется сообщение, что редактор vi применяется как редактор, заданный по умолчанию. Затем vi устанавливается в качестве редактора, и сценарий завершается.
Если редактор vi не установлен, пользователю поступает запрос, следует ли установить это значение. Проверка выполняется независимо от регистра, в котором находится символ у. Если пользователь не вводит значения, отличные от у или у, сценарий завершается.
На данном этапе пользователю предлагается ввести тип редактора. Затем выполняется проверка, не установлен ли данный редактор, а также уточняется, не нажимал ли пользователь во время проверки $editor ="" клавишу [Return]. Действительно эта проверка реализована лучше, чем -z $editor, но оба этих метода приводятся лишь в качестве иллюстрации. Если результаты проверки будут отрицательны, на экран выводится сообщение, что применяется редактор vi, причем значение vi присваивается переменной editor.
Если пользователь вводит имя для переменной editor, происходит присвоение и экспорт этого имени.
18.3.19. Проверка кода завершения последней команды
До сих пор каталог создавался путем передачи названия каталога в сценарий. Затем сценарий запрашивал пользователя, создан ли каталог. В следующем примере создается каталог, и все файлы *.txt копируются из текущего каталога в новый каталог. В приведенном сценарии с помощью кода завершения последней команды проверяется успешность выполнения каждой из команд. Если результаты выполнения команд неудовлетворительны, пользователю направляется соответствующее сообщение.
$ pg ifmkd±r2
#!/bin/sh
#ifmkdir2
DIR_NAME=testdirec
#где мы находимся?
THERE=`pwd`
# перенаправление потока вывода в системную корзину
mkdir $DIR_NAME > /dev/null 2>&1
# каталог ли это ?
if [ -d $DIR_NAME ] ; then
# можно ли применить к каталогу команду cd
cd $DIR_NAME
if [ S? = 0 ]; then
# да, можно
HERE=`pwd`
cp $THERE/*.txt $HERE
else
echo "Cannot cd to $DIR_NAME" >&2
exit 1
fi
else
echo "cannot create directory $DIR_NAME" >&2
exit 1
fi
18.3.20. Добавление и проверка целых значений
В следующем примере рассматривается проверка чисел. Сценарий содержит набор значений счетчика, который легко изменяется при вводе пользователем нового числа. Затем сценарий добавляет это новое значение к постоянному значению, равному 100. Ниже показано, как выполняется подобный сценарий.
Пользователь может изменить значение путем ввода нового значения, или же ничего не менять, нажав клавишу [Return]. Затем текущее значение выводится на экран, и сценарий завершается.
Если пользователь вводит у или у, поступает приглашение на ввод нового значения, которое добавляется к счетчику. Если пользователь нажимает клавишу [Return], сценарий с помощью команды echo сообщает, что счетчик сохраняет старое значение. Когда пользователь вводит значение, проверка чисел позволяет уточнить, является ли это значение числом. Если это так, значение добавляется к значению counter и затем отображается на экране.
$ pg ifcounter
#!/bin/sh
# ifcounter
COUNTER=100
echo "Do you wish to change the counter value currently set at $COUNTER ? [y...n] :"