Раздел 7

УПРАВЛЯЮЩИЕ КОНСТРУКЦИИ SHELL

Обзор

Shell имеет управляющие конструкции, которые позволяют осуществлять условное выполнение командной строки и циклы. Этот раздел описывает использование операторов test, if-else, while, continue, break и exit. Здесь также обсуждается вопрос как создать и использовать вашу собственную простую функцию.

ЦЕЛИ

1. Использовать оператор test для :
Проверки статуса файла (полномочия и размер).
Сравнения символьных строк.
Сравнения численных значений строк.
2. Использовать оператор if для условного выполнения командной строки.
3. Использовать управляющую конструкцию
if-else для условного выполнения командной строки.
4. Использовать оператор
exit для завершения процедур.
5. Использовать оператор
while для циклического выполнения операторов и команд.
6. Использовать оператор
continue для возвращения на вершину цикла.
7. Использовать оператор
break для разрыва цикла, когда удовлетворены указанные условия.
8. Создать простую функцию внутри программы
shell.

Статус завершения

Команда, которая запускается в системе UNIX, возвращает статус завершения в shell. Статус завершения это число от 1 до 255, обозначающее, как завершилась программа. В основном статус завершения 0 означает, что команда прошла успешно, а статус завершения от 1 до 255 означает, что произошел сбой. Обычно сбой происходит из-за неправильного использования команды. Не существует стандартного множества ненулевых значений для команд.

Внутри процедур shell статус завершения часто определяет направления потока выполнения в условных операторах и операторах цикла.

Предопределенная переменная shell ${?}

Значение предопределенной переменной shell ${?} представляет собой статус завершения последней команды в режиме переднего плана (до сих пор в этом курсе вы встречались только с программами выполняемыми в режиме переднего плана). Чтобы увидеть значение ${?}, наберите echo ${?} в ответ на подсказку shell.

В примере на развороте, предположим, что файл nofile не существует. Когда команда cat пытается отобразить несуществующий файл, выводится сообщение об ошибке и команда cat завершается не отобразив файл. Вывод 2 первой команды echo, означает что команда cat (последняя выполненная программа) не была успешной. Вывод 0 второй команды echo, означает, что последняя выполненная программа, команда echo, завершилась успешно.

Оператор test

Внутри процедур shell оператор test часто обеспечивает статус завершения для условных операторов и операторов цикла. Оператор test возвращает статус завершения 0 (успех), если проверяемое условие истинно; иначе он возвращает статус завершения 1 (ошибка или ложь). Вы можете также использовать ${?}, чтобы получить доступ к статусу завершения оператора test.

Оператор test оперирует с тремя условиями: статус файла, сравнение строк и численное (целочисленное) сравнение. Все три способа использования оператора test объяснены на следующих страницах.

СТАТУС ЗАВЕРШЕНИЯ

0 ЕСЛИ КОМАНДА ЗАВЕРШИЛАСЬ УСПЕШНО

1 ЕСЛИ БЫЛ СБОЙ

ПРЕДОПРЕДЕЛЕННАЯ ПЕРЕМЕННAЯ $? ОТОБРАЖАЕТ СТАТУС ВЫХОДА ПОСЛЕДНЕЙ КОМАНДЫ

ПРИМЕР: ${?}

$ cat nofile<RET>

cat: cannot open nofile

$ echo ${?}<RET>

2

$ echo ${?}<RET>

0

$

ОПЕРАТОР test

ОПЕРИРУЕТ С УСЛОВИЯМИ

- Статус файла

- Сравнение строк

- Численное сравнение

СТАТУС ЗАВЕРШЕНИЯ 0, ЕСЛИ УСЛОВИЕ ИСТИННО

СТАТУС ЗАВЕРШЕНИЯ ОТ 1 ДО 255, ЕСЛИ УСЛОВИЕ ЛОЖНО

Операции со статусом файла оператора test

Оператор test оперирует со статусом существующего файла, рассматривая полномочия пользователя и тип файла. Файл, статус который вы хотите проверить, становится аргументом команды test, как это видно из приведенного ниже формата:

ФОРМАТ

test -r имя_файла # истина, если файл доступен по чтению

test -w имя_файла # истина, если файл доступен для записи

test -x имя_файла # истина, если файл существует и исполним

test -s имя_файла # истина, если файл имеет ненулевой размер

test -f имя_файла # истина, если файл существует

test -d имя_файла # истина, если файл является каталогом

test -h имя_файла # истина, если файл связан символьно

Вы можете окружать каждую секцию оператора test пробелами.

Если файл существует с указанным опцией атрибутом, оператор test возвращает статус завершения 0; иначе test возвращает статус завершения 1.

Режим доступа к файлу зависит от трех классов пользователей: владелец, группа и прочие. Если лицо требующее проверки является владельцем файла, система проверяет полномочия владельца. Если запрашивающий не владелец, а член группы владельца, система проверяет полномочия группы. Если запрашивающий не является ни владельцем ним членом группы владельца, система проверяет полномочия прочих.

Все возможности shell в генерации строк, литералы, переменные shell, подстановка команд или генерация аргументов, могут создавать имена файлов. Как бы то ни было, аргумент имя файла (строка) должен быть представлен. Если подстановка запрашивает генерацию имени файла, заключите запрос подстановки в двойные кавычки для нулевого значения.

ОПЕРАЦИИ СО СТАТУСОМ ФАЙЛА
ОПЕРАТОРА
test

Из вашего каталога login

$ ls -l<RET>

total 2

drwxr-xr-x 2 slf greaser 32 Sep 28 16:20 unit7

-rw-r--r-- 1 slf greaser 5 Sep 28 16:20 perm

ПРИМЕР 1:

$ test -d unit7<RET>

$ echo ${?}<RET>

0

ПРИМЕР 2:

$ test -x perm<RET>

$ echo ${?}<RET>

1

$

ПРИМЕР 3:

$ test -d "${HOME}"<RET>

$ echo ${?}<RET>

0

Логическое И и логическое ИЛИ

В одном операторе test можно сочетать две или более проверок с помощью "логического и" и "логического или". Для проверки "логического и" используйте слово '-a'. Для статуса завершения 0 оба условия должны быть истинны. Смотри пример 1 на развороте. Для проверки "логического или" используйте слово '-o'. только одно условие должно быть истинно для статуса завершения 0.

При одновременном использования "логического и" и "логического или" '-a' имеет более высокий приоритет, чем '-o'. Вы можете использовать скобки для группирования или изменения приоритета, но каждая левая и правая скобки должны быть в кавычках. Пример 2 на развороте использует для буквализации скобок, которые группируют операторы отрицания, обратные слэши (\) вместо кавычек.

ОТРИЦАНИЕ УСЛОВИЙ

Знак ! отрицает проверяемое условие. Вы должны поставить пробел до и после него. Например,

test ! -d имя_файла

проверяет не является ли имя_файла каталогом. Если имя_файла не каталог, оператор test возвращает статус завершения 0. См. пример на развороте.

ЛОГИЧЕСКОЕ И И ЛОГИЧЕСКОЕ ИЛИ

Из вашего каталога login

$ ls -l<RET>

total 2

drwxr-xr-x 2 slf greaser 32 Sep 28 16:20 unit7

-rw-r--r-- 1 slf greaser 5 Sep 28 16:20 perm

ПРИМЕР 1:

$ test -d unit7 -a -x unit7<RET>

$ echo ${?}<RET>

0

ПРИМЕР 2:

$ test ! -d unit7<RET>

$ echo ${?}<RET>

1

ПРИМЕР 3:

$ test ! ( -d unit7 -a -x unit7 )<RET>

$ echo ${?}<RET>

1

Сравнение строк оператором test

Оператор test различает два типа сравнения строк:

1. = проверка на равенство (идентичность строк)

2. != проверка на неравенство (различие строк)

Когда две строки проверяются на равенство, обе строки должны быть идентичны посимвольно, и также должны иметь одинаковую длину, чтобы статус завершения был 0. Если между ними есть хоть какое-либо различие, статус завершения проверки будет 0.

ФОРМАТ

test "строка1" = "строка2" (проверка на равенство)

или

test "строка1" != "строка2" (проверка на неравенство)

Вы должны окружить операторы отношения "=" и "!=" пробелами, или иначе оператор test будет интерпретировать их как часть следующей за ними проверяемой строки. Хотя заметим, что при проверке на неравенство между "!=" пробелы не требуются.

Любое средство shell, как переменные shell или подстановки команд могут обеспечивать строки. Как бы то ни было, аргумент (строка) должен быть представлен. Если запрос подстановки генерирует строку, заключите запрос подстановки в двойные кавычки чтобы разрешить нулевое значение.

Иногда, когда строка обеспечивается подстановкой shell, существует возможность нулевой подстановки. Например, пользователь имея подсказку для ввода может просто нажать <RET>. В этом случае переменная получает нулевое (пустое) значение. Поэтому, вы должны заключить любую подстановку shell аргумента test в двойные кавычки.

Чтобы сравнить аргументы с нулем (пусто), введите пустое значение как один из аргументов. Пустое значение представляется как двойные кавычки "", ничего не заключающие внутри. Например если позиционный параметр не был определен, его значение пусто. Чтобы проверить существует ли первый позиционный параметр, сравните его с нулем:

$ test "${1}" = ""

Замечание: Если аргумент (строка) не заключен в двойные кавычки и имеет нулевое значение, shell удаляет строку из командной строки а test, терпит неудачу, так как ему недостает аргумента.

СРАВНЕНИЕ СТРОК ОПЕРАТОРОМ test

ПРИМЕР 1:

$ echo ${LOGNAME}<RET>

jas

$ test "slf" = "${LOGNAME}"<RET>

$ echo ${?}<RET>

1

ПРИМЕР 2:

$ echo ${TERM}<RET>

vt100

$ test "${TERM}" != "605"<RET>

$ echo ${?}<RET>

0

ПРИМЕР 3:

$ test "${TERM}" != "vt100"<RET>

$ echo ${?}<RET>

1

ПРИМЕР 4:

$ echo ${NOTSET}<RET>

$ test ${NOTSET} != "hello"<RET>

test: argument expected

$ test "${NOTSET}" = "hello"<RET>

$ echo ${?}<RET>

1

Численное сравнение оператором test.

Символьная
строка

Числовое
значение

"15"

15

"234.43

234

"442 Elm St"

442

"4312786**"

4312786

"Scott Steward"

0

Вы можете также использовать test для сравнения строк, которые начинаются с чисел. Первый символ строки в численном сравнении должен быть числом, но остальные символы строки могут быть нечисленными. Shell сравнивает все последовательные числа слева направо пока не достигает первого нечислового символа. Строка, которая не начинается с числа эквивалентна 0. Справа приведен пример численного сравнения

Вы можете использовать команду test, чтобы проверить является ли содержащееся в строке число численно равным, не равным, большим чем, меньшим или равным, меньшим чем, меньшим или равным числу, содержащемуся во второй строке. Формат:

test "строка1" eq "строка2" # равно

test "строка1" ne "строка2" # не равно

test "строка1" gt "строка2" # больше чем

test "строка1" ge "строка2" # больше или равно

test "строка1" lt "строка2" # меньше чем

test "строка1" le "строка2" # меньше или равно

Все операторы должны использоваться как отдельные слова в командной строке, и быть окружены пробелами. Если строка генерируется запросом подстановки, заключите строку в двойные кавычки.

Альтернативный формат оператора test.

Еще один способ записать оператор test - заключить команду тестирования в квадратные скобки []. Этот метод облегчает чтение и ввод процедур shell. Формат:

[ expr ]

Вы должны оставить пробел после левой квадратной скобки ([) и перед правой (]). Например:

[ -r filename ] то же, что и test -r filename

[ "${LOGNAME}" = slf ] то же, что и test "${LOGNAME}" = slf

[ 'date +%d' -eq 14 ] то же, что и test 'date +%d' -eq 14

СРАВНЕНИЕ ЧИСЕЛ ОПЕРАТОРОМ test

ПРИМЕР 1:

$ today=`date +%d`<RET>

$ echo ${today}<RET>

07

$ test "${today}" -eq "14"<RET>

$ echo ${?}<RET>

1 не равно

$ test "${today}" -eq "7"<RET>

$ echo ${?}<RET>

0 равно

$ test "${today}" = "7"<RET>

$ echo ${?}<RET>

1 не равно (строковый вариант test)

ПРИМЕР 2:

$ test "224 Elm St." -eq "224 Pine Rd."<RET>

$ echo ${?}<RET>

0 равно (числовой вариант test)

$ test "uc1080" -eq "uc1070"<RET>

$ echo ${?}<RET>

0 равно (числовой вариант test)

$ test "1080uc" -eq "1070uc"<RET>

$ echo ${?}<RET>

1 не равно (числовой вариант test)

Условное выполнение: оператор if.

Подобно большинству языков программирования, shell допускает условное выполнение с помощью оператора if. В этом курсе обсуждаются форматы if-then-fi и
if-then-else -fi.

В этом курсе не рассматривается конструкция elif.

ФОРМАТ: if-then-fi

if

команда

команда

тестирующая_команда

then

команда

команда

команда

fi

Управляющая конструкция if имеет три ключевых слова: if, then и fi. Ключевое слово if начинает оператор. Все команды между ключевыми словами if и then выполняются безусловно. Команды между ключевыми словами then и fi выполняются условно, основываясь на статусе завершения последней команды перед словом then.

Если последняя команда перед словом then имеет статус завершения 0 (истина), список команд между ключевыми словами then и fi выполняется. Но если последняя команда перед словом then имеет статус завершения 1 (ложь). список команд между ключевыми словами then и fi игнорируется. В обоих случаях выполнение возобновляется после ключевого слова fi.

Хотя тестирующая команда это обычно оператор shell test, вы можете использовать любую команду, возвращающую статус завершения. Shell проверяет статус только на равенство нулю. Хотя между if и then могут находиться любые команды, требуется только тестирующая команда.

В примере 1 на развороте, программа showit принимает имя файла как позиционный параметр. Если файл существует и доступен по чтению, программа отображает содержимое этого файла с помощью команды cat. Если условие ложно, программа завершается.

Shell не допускает вложенного оператора if.

В примере 2 на развороте, программа instock.1 читает номер или имя детали с клавиатуры и присваивает введенное значение переменной item. Если это значение присутствует в строках файла inventory, программа выводит эти строки. Если значение не включено в строки файла inventory, программа завершается.

УСЛОВНОЕ ВЫПОЛНЕНИЕ: ОПЕРАТОР if

ПРИМЕР 1:

$ cd unit7<RET>

$ cat showit<RET>

# The program showit takes a file name

# as a positional parameter. If the file is

# readable, then display its contents with cat.

if

test -r $1

then

cat $1

fi

ПРИМЕР 2:

$ cat instock.1<RET>

echo "Enter part number or name: c"

read item

if

test "${item}" != ""

then

echo "PART\t\tDESCRIPTION\tSUPPLIER\tPRICE\tOOH"

echo "====\t\t===========\t========\t=====\t==="

grep -i "${item}" inventory #${HOME}/unit7/inventory

fi

$ instock.1<RET>

Enter part number or name: nail<RET>

PART DESCRIPTION SUPPLIER PRICE QOH

==== =========== ======== ===== ===

C1987653 Common 1D Nail Wafer Supplies .24 470

C1987655 Masonry nail Metal Supply. 31 245

P8862943 Roofing Nail Metal Supply 100.43 20

$ instock.1<RET>

Enter part number or name: <RET>

$

Оператор exit

Команда, запущенная в системе UNIX, возвращает статус выхода в shell. Аналогично процедура shell может возвращать статус завершения в вызвавшую ее shell. Статус выхода зависит от того как завершилась процедура.

Оператор exit завершает выполнение shell. Оператор exit со следующим за ним числом завершает процедуру и возвращает это число как статус завершения в родительский shell. Число может находиться в пределах 0-255. По соглашению, статус завершения 0 предполагает успешное завершение, ненулевой статус завершения предполагает ошибку.

Чтобы вернуть статус завершения из написанной вами программы, используйте оператор exit с числом - статусом. Если вы не определите это число статуса, то статус завершения по умолчанию будет равен статусу завершения последней команды, выполненной перед оператором exit.

Статус завершения команды grep

Команда grep возвращает статус завершения 0 (успех), если находит соответствующий шаблон. Она возвращает статус завершения 1, если не находит указанный шаблон и статус завершения 2, если происходит другая ошибка.

Пример, areyou.on, на развороте проверяет работает ли на компьютере другой пользователь. Желаемое входное имя должно быть представлено как аргумент для программы areyou.on. Первый оператор if проверяет имеется ли аргумент в командной строке. Если аргумент представлен не был, программа выводит сообщение и завершает работу со статусом завершения 2 (неудачное завершение). Если аргумент был представлен, программа ищет это входное имя и перенаправляет вывод в /dev/null, создавая свой собственный вывод.

Во втором операторе if, команда grep справа от символа транспортера (|) является тестирующей командой. Если предложенное входное имя соответствует некоторой строке из вывода команды who, то выводится сообщение и программа завершается со статусом завершения 0. Если входное имя не было найдено, программа завершается со статусом завершения 1.

ОПЕРАТОР EXIT

$ cat areyou.on<RET>

# program name: areyou.on

# exit status: 2 - no login id specified

(не определено входное имя)

# 0 - normal completion

(нормальное завершение)

# purpose: To see if someone with the

(цель: увидеть работает ли пользователь

# specified login is logged on.

(с указанным входным именем)

#

if

test "${1}" = ""

then

echo "\n\tUsage: ${0} login-id\n"

exit 2

fi

if

who | grep ${1} > /dev/null

then

echo "\n${1} is logged on the system!"

fi

$ areyou.on sds<RET>

sds is logged on the system!

$ echo ${?}<RET>

0

$ areyou.on<RET>

Usage: areyou.on login-id

$ echo ${?}<RET>

2

$

Условное выполнение: оператор if-else

Оператор shell if позволяет выполнять один из двух условных списков команд, основываясь на результатах проверки условия.

ФОРМАТ: if-then-else-fi

if

команда

тестирующая команда

then (тестирующая команда - ИСТИНА)

команда

команда

else (тестирующая команда - ЛОЖЬ)

команда

команда

fi

Конструкция if-else имеет четыре ключевых слова: if, then, else и fi. Ключевое слово if начинает оператор. Все команды между ключевыми словами if и then выполняются безусловно. Список команд между ключевыми словами if и then, также как и список команд между ключевыми словами else и fi выполняется условно в зависимости от статуса завершения ПОСЛЕДНЕЙ команды перед ключевым словом then.

Если последняя команда перед ключевым словом then имеет статус завершения 0 (истина), выполняется только список команд между ключевыми словами then и else. Но если последняя команда перед ключевым словом then имеет статус 1 (ложь), то выполняется только список команд между ключевыми словами else и fi. В любом случае выполнение продолжается после ключевого слова fi.

В примере на развороте, первый оператор test определяет был ли представлен программе аргумент. Если аргумент был представлен, статус завершения оператора test - 0 (истина) и аргумент становится значением переменой item. Если аргумент не определен, статус завершения оператора test -1 (ложь) и программа подсказывает, что необходимо ввести значение item.

Второй оператор if проверяет имеет ли переменная item пустое значение. Если значение не пусто, команда grep ищет его в файле inventory. Если представлено пустое значение, выводится сообщение об ошибке и программа заканчивает работу со статусом завершения 2.

УСЛОВНОЕ ВЫПОЛНЕНИЕ:
ОПЕРАТОР
if-else

$ cat instock.2<RET>

if

test "${#}" -eq 1

then

item="${1}"

else

echo "Enter part number or name: c"

read item

fi

if

test "${item}" != ""

then

echo "PART\t\tDESCRIPTION\tSUPPLIER\tPRICE\tQOH"

echo "====\t\t===========\t========\t=====\t==="

grep -i "${item}" inventory # ${HOME}/unit7/inventory

else

echo "\n\t${0}: No part specified"

exit 2

fi

$

$ instock.2<RET>

Enter part number or name: nail<RET>

PART DESCRIPTION SUPPLIER PRICE QOH

==== =========== ======== ===== ===

C1987653 Common 1D Nail Wafer Supplies .24 470

C1987655 Masonry nail Metal Supply. 31 245

P8862943 Roofing Nail Metal Supply 100.43 20

$ instock.2<RET>

Enter part number or name:<RET>

instock.2: No part specified

$ instock.2 cable<RET>

PART DESCRIPTION SUPPLIER PRICE QOH

==== =========== ======== ===== ===

B1265347 100 ft Cable Wafer Supplies 34.86 32

$

Организация циклов с помощью оператора while.

Оператор while условно повторяет выполнение операторов или команд.

ФОРМАТ: while-do-done

while

команда

.

.

.

тестирующая_команда

do

команда

.

.

.

команда

done

Ключевыми словами являются while, do, и done. Ключевое слово while начинает оператор. Все команды между ключевыми словами while и do выполняются условно, в зависимости от статуса завершения последней команды перед ключевым словом do.

Если последняя команда перед ключевым словом do имеет статус завершения 0 (истина), выполняется список команд между ключевыми словами do и done. После достижения ключевого слова done, поток выполнения совершает циклическое возвращение назад к ключевому слову while, где список команд между ключевыми словами while и do выполняется снова. Если статус завершения перед ключевыми словом do все еще 0 (истина), команды между ключевыми словами do и done выполняются снова. Этот оператор цикла повторяется, пока результат последней команды тестирования не ложь.

Как только статус завершения последней команды перед ключевым словом do становится 1 (ложь), список команд между ключевыми словами do и done игнорируется. Выполнение продолжается после ключевого слова done.

Shell предусматривает вложение операторов while.

Пример на развороте позволяет вам продолжать поиск в файле inventory пока для его завершения не нажата клавиша выхода <CTRL/d>. Оператор test проверяет не имеет ли переменная item пустое значение (""). Если значение не пусто, команда grep начинает его поиск в файле inventory. Если представлено пустое значение, выводится сообщение об ошибке. Так как конец циклической конструкции является и концом программы, процедура заканчивается только тогда, когда пользователь нажмет <CTRL/d>.

ОРГАНИЗАЦИЯ ЦИКЛОВ
С ПОМОЩЬЮ ОПЕРАТОРА
while

$ cat instock.3<RET>

while

echo "\nEnter part number or name, or <CTRL/d> to quit:\c"

(введите номер или имя детали, или <CTRL/d> (завершение))

read item

do

if

test "${item}" != ""

then

echo "PART\t\tDESCRIPTION\tSUPPLIER\tPRICE\tQOH"

echo "====\t\t===========\t========\t=====\t==="

grepi "${item}" inventory # ${HOME}/unit7/inventory

else

echo "nt${0}: no part specified"

fi

done

$ instock.3<RET>

Enter part number or name, or <CTRL/d> to quit: nail<RET>

PART DESCRIPTION SUPPLIER PRICE QOH

==== =========== ======== ===== ===

C1987653 Common 1D Nail Wafer Supplies .24 470

C1987655 Masonry nail Metal Supply. 31 245

P8862943 Roofing Nail Metal Supply 100.43 20

Enter part number or name, or <CTRL/d> to quit: cable<RET>

PART DESCRIPTION SUPPLIER PRICE QOH

==== =========== ======== ===== ===

B1265347 100 ft Cable Wafer Supplies 34.86 32

Enter part number or name, or <CTRL/d> to quit: <RET>

instock.3: No part specified

(деталь не определена)

Enter part number or name, or <CTRL/d> to quit: <CTRL/d>

$

Оператор continue

Оператор continue пропускает оставшиеся операторы в теле цикла и возвращается вновь к началу цикла. Вы можете использовать оператор continue в любой циклической структуре. Например в теле цикла while, когда shell достигает оператора continue он передает управление потоком выполнения обратно к началу цикла while. При этом команды между ключевыми словами while и do выполняются снова.

ФОРМАТ: continue [n]

По умолчанию, оператор continue без опции - числа [n] начинает выполнение вновь с вершины цикла непосредственно над ней. Например:

while (второй цикл)

do

while (первый цикл)

do

continue

done

done

Для вложенных циклов в формате continue предусмотрена опцию [n], которая устанавливает количество циклов которое отсчитывает shell, возвращаясь по оператору continue. Например continue 2 переведет вас на второй оператор while над текущим continue.

while (третий цикл)

do

while (второй цикл)

do

while (первый цикл)

do

continue 2

done

done

done

В примере на развороте, программа instock.4 - это еще одна программа, которая заканчивается только по нажатию пользователем клавиши <CTRL/d>. Когда оператор read получает на вводе <CTRL/d>, он возвращает ненулевой (ложь) статус завершения. Так как оператор read - последний оператор перед ключевым словом do, ненулевой статус завершения заканчивает цикл while.

Если пользователь вводит пустое сообщение, как например <RET>, это обрабатывается как нефатальная ошибка. Достается первый оператор continue и выполнение возвращается на вершину цикла, где программа вновь запрашивает имя и номер детали. Если представлено ненулевое значение , команда grep ищет его в файле inventory. По достижении второго оператора continue программа возвращается на вершину цикла, где вновь запрашивает номер или имя детали.

ОПЕРАТОР continue

$ cat instock.4<RET>

while

echo "\nEnter part number or name, or <CTRL/d> to quit: \c"

read item

do

if

test "${item}" = ""

then

continue

fi

echo "PART\t\tDESCRIPTION\tSUPPLIER\tPRICE\tQOH"

echo "====\t\t===========\t========\t=====\t==="

if

grep -i "${item}" inventory #${HOME}/unit7/inventory

then

continue

else

echo "\t${item}: not recognized, please try again"

fi

done

$ instock.4<RET>

Enter part number or name, or <CTRL/d> to quit: <RET>

Enter part number or name, or <CTRL/d> to quit: capacitor<RET>

PART DESCRIPTION SUPPLIER PRICE QOH

==== =========== ======== ===== ===

T3048572 Capacitor Unlimited Parts .32 200

Enter part number or name, or <CTRL/d> to quit: curd<RET>

PART DESCRIPTION SUPPLIER PRICE QOH

==== =========== ======== ===== ===

curd: not recognized, please try again

Enter part number or name, or <CTRL/d> to quit: cord<RET>

PART DESCRIPTION SUPPLIER PRICE QOH

==== =========== ======== ===== ===

R1289675 Power Cord Elis Power 4.65 10

Enter part number or name, or <CTRL/d> to quit: <CTRL/d>

$

Оператор break

Оператор break пропускает оставшиеся команды в теле цикла (разрывает цикл) и продолжает работу после конца цикла. Вы можете использовать оператор break в любой циклической конструкции. Например, внутри тела цикла while, когда shell достигает оператора break, цикл заканчивается и выполнение продолжается после ключевого слова done.

В отличие от языка C, оператор break завершает только цикл или циклы.

ФОРМАТ: break [n]

По умолчанию, оператор break без опции - числа [n] непосредственно завершает последнее вхождение в цикл. Для вложенных циклов, формат break имеет опцию [n], которая устанавливает количество циклов, которые разрывает shell. Обычно break используют, чтобы разорвать только одну циклическую конструкцию. Если вы используйте break, чтобы разорвать более чем одну циклическую конструкцию, сделайте точные комментарии в исходном файле, сообщающие который из циклов разрывается и куда передается управление.

В примере на развороте, программа instock.5 заканчивает работу с нажатием пользователем клавиши <RET>. Оператор test проверяет не имеет ли переменная item пустое значение (""). Если представлено пустое значение, то оператор break разрывает оператор while и программа завершается.

Если представлено ненулевое значение то, команда grep ищет его в файле inventory. Если деталь найдена, то оператор continue возвращает управление на вершину цикла while и программа вновь запрашивает имя и номер детали. Если значение не найдено, то программа подсказывает пользователю попытаться снова. После достижения ключевого слова done, поток выполнения возвращается назад к ключевому слову while, где список команд между ключевыми словами while и do выполняется снова.

ОПЕРАТОР break

$ cat instock.5<RET>

while

echo "\nEnter part number or name, or <RET> to quit: \c"

read item

do

if

test "${item}" = ""

then

break

fi

echo "PART\t\tDESCRIPTION\tSUPPLIER\tPRICE\tQOH"

echo "====\t\t===========\t========\t=====\t==="

if

grep -i "${item}" inventory #${HOME}/unit7/inventory

then

continue

else

echo "t${item}: not recognized, please try again"

fi

done

$ instock.5<RET>

Enter part number or name, or <RET> to quit: capacitor<RET>

PART DESCRIPTION SUPPLIER PRICE QOH

==== =========== ======== ===== ===

T3048572 Capacitor Unlimited Parts .32 200

Enter part number or name, or <RET> to quit: cord<RET>

PART DESCRIPTION SUPPLIER PRICE QOH

==== =========== ======== ===== ===

R1289675 Power Cord Elis Power 4.65 10

Enter part number or name, or <RET> to quit: <RET>

$

Функции Shell.

Процедуры shell - это только один способ сгруппировать команды под одним именем. Функции shell также являются сериями команд под одним именем, но они хранятся в среде активного процесса shell.

Процедуры и функции shell имеют два общих свойства: они выполняются, когда вы набираете их имя и они позволяют вам не набирать повторно одни и те же команды.

Тем не менее, процедуры shell отличаются от функций shell. Процедура shell хранится в файле, родительский shell интерпретирует ее командные строки, и процесс потомок выполняет их. Но функция уже определена для процесса shell, так что тот же shell, который интерпретирует функцию и выполняет ее. В работе с функциями не нужно создавать процесс потомок shell или осуществлять поиск для переменной PATH. С этой точки зрения функции более эффективны.

Так как функции shell доступны только для текущего shell, они существуют только пока существует shell. Вы не может экспортировать функции; вместо этого вы должны переопределить функцию для другого shell, который в ней нуждается.

На развороте приведено два способа написания функций. В обоих способах имя - это имя функции. Скобки () идентифицируют имя как функцию shell. Далее следует левая фигурная скобка { с последующим пробелом. Затем вы набираете серию команд, которые определяют функцию, отделяя команды точкой с запятой ; или <RET>. Заметим, что последняя команда заканчивается точкой с запятой ; или <RET>. Правая фигурная скобка } завершает определение функции.

Чтобы выполнить функцию, просто наберите ее имя. Вы можете также определить и использовать функцию внутри процедуры shell. Чтобы иметь постоянный доступ к функции определите ее в вашем файле profile.

Предположим вы хотите изменить значение вашей переменой PS1, чтобы отобразить текущий каталог. Процедура shell не может сделать этого, так как ее будет выполнять процесс потомок. Когда завершается процесс потомок, переменная PS1 изменяется. В этой ситуации вам нужна функция.

В примере 1 на развороте, функция goto изменяет вашу переменную PS1 для отображения текущего каталога, где бы вы ни набрали goto вместо cd в ответ на подсказку shell.

ФУНКЦИИ SHELL

$ имя() { команда; команда; команда }<RET>

$

ИЛИ

$ имя() {

команда <RET>

команда <RET>

команда <RET>

}<RET>

$

ПРИМЕР 1:

· Определим goto:

$ goto() { cd ${1} ; PS1="[`pwd`] "; }<RET>

· Используем goto:

$ goto /etc<RET>

[/etc] pwd<RET>

/etc

[/etc] goto<RET>

[/home/stu2]

Выводы и Упражнения

Выводы урока

Этот урок описывает:

Статус завершения

0 успех или истина
1-255 ошибка или ложь

оператор test со статусом файла

- -r файл существует и доступен по чтению
- -w файл существует и доступен по записи
- -x файл существует и исполним
- -s файл существует и имеет ненулевой размер
- -f файл существует и является обычным
- -d файл существует и является каталогом
- -h файл существует и связан символьно
логическое и
-a, логическое или -o
отрицание !

сравнение строк оператором test

равенство =
неравенство !=

численное сравнение оператором test

-eq равно
- -ne не равно
- -gt больше
- -ge больше или равно
- -lt меньше
- -le меньше или равно

оператор if для условного выполнения. Ключевые слова: if, then, fi

оператор exit для возвращения статуса завершения из вашей процедуры

оператор if-else выполняет команды которые определяются проверкой   условия. Ключевые слова: if, then, else, fi

оператор while условно повторяет команды. Ключевые слова: while, do,  done

оператор continue возвращается на вершину цикла, не выполняя некоторые  команды в теле цикла. Ключевое слово: continue

оператор break разрывает цикл и продолжает выполнение команд находящихся  после цикла. Ключевое слово: break

Функции это:

серия команд сгруппированных вместе под одним именем
определенная для процесса shell так, что для ее выполнения не создается         нового процесса.

Упражнения 7.1.А

1. Войдите в ваш входной каталог. Используйте оператор test, чтобы определить в этом каталоге следующее.

а. Существует ли в каталоге unit7 файл calendar и имеет ли он право доступа писать?

б. Существует ли файл phone и является ли он каталогом?

в. Является ли каталогом файл mail.list?

г. Имеет ли ваша переменная TERM значение vt100?

д. Имеет ли ваша переменная LOGNAME значение student1?

е. Больше ли ваш возраст размера вашей талии?

2. Смените каталог на unit7. Это первая программа в последовательности программ, которые надстраиваются одна над другой. Напишите программу shell с именем guess1, которая:

а. сохраняет секунды из команды date в переменную

б. Запрашивает ввод числа в пределах от 0 до 59.

в. Читает ваш ответ.

г. Если ваш ответ равен записанным секундам, печатает число и сообщение как вы удачливы.

3. Скопируйте guess1 в файл guess2. Измените guess2 так, чтобы:

а. Если ваш ответ равен записанным секундам, вывести число и сообщение, говорящее как вы удачливы и завершить программу.

б. Если ваш ответ не равен записанным секундам, вывести сообщение, говорящее "очень плохо", и предоставить возможность попытаться еще.

4. Скопируйте guess2 в файл guess3. Измените guess3 так, чтобы

а. Программа запрашивала у вас число (от 0 до 59) и читала ваш ответ столько раз сколько необходимо, пока ваш ответ не совпадет с запомненными секундами. (цикл)

б. Она выводила значения, ближайшие к вашему ответу сверху и снизу. Например: "Следующий ответ находится между 5 и 20".

в. Когда ваш ответ совпадает с записанными секундами, выводиться число и прощальное сообщение.

5. В этом упражнении вам следует написать программу, называемую find.month, включающую функцию seecal. Функция seecal отображает календарь на один месяц. Функция find.month повторяет запрос до получения ответа n.

См., если нужно, на странице 7.1.19 пример оператора тестирования.

а. Функция seecal:

- Запрашивает у вас какого года календарь вы хотите видеть. Год в пределах
1-1999. Читает ваш ответ.

 - Запрашивает у вас календарь какого месяца вы хотите видеть. Месяц в пределах 1-12. Читает ваш ответ.

- Отображает календарь для введенных месяца и года.

б. Программа find.month:

- Спрашивает хотите ли вы видеть календарь и читает ответ.

- Если ответ пуст, повторяет запрос.

 - Если ответ y, вызывается seecal.

- Если ответ n, программа завершается. с благодарственным сообщением.

- Если ответ иной, чем y,n или пусто, вам задается вопрос желаете ли вы видеть календарь