Компания ALT Linux
Опубликован: 14.12.2004 | Доступ: свободный | Студентов: 12289 / 1476 | Оценка: 4.19 / 3.84 | Длительность: 18:18:00
ISBN: 978-5-9556-0019-1
Лекция 11:

Shell как язык программирования и интегратор

< Лекция 10 || Лекция 11: 12345 || Лекция 12 >

Порядок выполнения команд

В алгоритмически полном языке программирования должна быть возможность выполнения различных действий в зависимости от условий - проще говоря, оператор if. Он, конечно, есть и в shell:

$ if [ 5 -gt 6 ]; then echo "Bug"; else echo "Good"; fi
Good

Обратите внимание на ключ -gt, означающий greater than, и на fi в конце оператора - так в shell устроены операторные скобки (лексемы if, then, необязательное else и fi ограничивают условие, условную часть и необязательную противоусловную часть; они могут находиться в одной строке, а могут и в разных).

Оказывается, эта простая конструкция очень неплохо доработана для связывания команд. Начать с того, что [ - это совсем не конструкция языка, а утилита:

$ ls -ial /bin/[ /bin/test
35 -r-xr-xr-x 2 root wheel 89992 5 июн 2003 /bin/[
35 -r-xr-xr-x 2 root wheel 89992 5 июн 2003 /bin/test

Как мы видим, [ и test - имена одного и того же файла (с индексным дескриптором 35) откуда, между прочим, следует, что описание содержимого квадратных скобок стоит искать в руководстве по test, а не в руководстве по sh. Команда test принимает такие же точно параметры, что и [ (только ей не нужна завершающая квадратная скобка). Это значит, что [ 5 -gt 6 ] - на самом деле самая обычная команда, и после if может использоваться не только она, но и любая другая команда UNIX, и даже несколько. Все их if запустит и проверит код возврата последней. Если команда выполнилась успешно, код возврата будет нулевым, и if выполнит условную часть. Если неуспешно - ненулевым (тогда он равен номеру ошибки), и if выполнит противоусловную часть.

Это слегка расходится с распространенным (по вине языка Си) мнением, что в условных выражениях "ложь" представляется нулем, а "истина" - не нулем; зато в сценариях приносит немало пользы. Код возврата (называемый также кодом ошибки ) только что завершившейся команды shell записывает в переменную ?, и его можно обработать с помощью оператора выбора case $? ... esac, описанного в руководстве.

У команды test, помимо арифметических сравнений, есть немало других ключей для нужд сценариев и связи с системой. Например, test -z "$N" выполняется успешно, если переменная N пуста, test -f имя_файла - если существует файл с таким именем, test -x имя_файла - если файл существует и доступен для выполнения, test файл_1 -ot файл_2 - если первый файл старше второго и т. п. С помощью test можно создавать командные сценарии, манипулирующие файлами, решать задачи архивирования, обновления и преобразования каталогов и т. п., не используя ничего, кроме shell и системных утилит.

Если необходимо выполнение одной команды поставить в зависимость от успешного выполнения другой, можно задействовать if. Однако легче воспользоваться конструкциями, перенесенными в shell из языка программирования Си: конъюнкцией (операция &&, логическое "и") и дизъюнкцией (операция ||, логическое "или") команд. В цепочке команда_1 && команда_2 вторая команда выполнится только в случае успешного выполнения первой; в цепочке команда_1 || команда_2 - только в случае неуспешного выполнения. Связывание команд нередко позволяет избавиться от многоэтажных вложенных if.

В shell, как и в каждом процедурном языке программирования, есть операторы цикла: цикл с условием while команды; do команды; done и цикл с перебором списка for переменная in список; do команды; done. Про первый из них можно сказать только, что истиной, как и в операторе if, считается успешное выполнение последней команды в секции условия. В цикле for списком называется последовательность слов и разделителей, которая обрабатывается по тем же правилам, что и командная строка. В результате цикл будет выполняться столько раз, сколько слов оказалось в списке, а переменная на каждом обороте цикла будет содержать очередное слово:

$ for N in 1 2 3 4 5; do echo -n "==$N=="; done
==1====2====3====4====5==$

Заметим, что, поскольку команда echo -n не печатает перевода строки в конце выдачи, результат вывелся в одну строчку; в конце этой же строки shell вывел и свою подсказку - $. Некоторые командные интерпретаторы (например, zsh ) очищают строку, в которой собираются вывести подсказку, что может слегка озадачить. В таком случае помогает echo без параметров, добавленная после всех команд, - она выводит дополнительный перевод строки:

zsh$ for N in 1 2 3 4 5; do echo -n "==$N=="; done # 
    выдачи мы не увидим :(
zsh$ for N in 1 2 3 4 5; do echo -n "==$N=="; done; echo # 
    вот она :)
==1====2====3====4====5==

Цикл вида for переменная; do команды; done в тексте сценария проходит по всем параметрам командной строки ; это то же самое, что и for переменная in "$@".... Мелочь, а приятно: чаще всего приходится разбираться с именами файлов, которые возникают в командной строке в великом множестве на месте шаблонов. Если в таком разборе в начале командной строки были ключи, а потом уже шел список файлов, удобно пользоваться командой shift, которая выбрасывает первый (или с первого по N-ный) параметр, ставит на его место второй (N+1-й) и т. д., то есть "сдвигает" список параметров.

< Лекция 10 || Лекция 11: 12345 || Лекция 12 >
Andranik Avakian
Andranik Avakian

41. УК РФ и Комментарии (ст. 273)

М. 2000 г. Издательство: ALT Linux, Институт Логики

Уголовный Кодекс РФ и комментарии к нему?

По ссылке открывается сайт документации Linux, раздел Linux Installation and Getting Started

Сергей Петровский
Сергей Петровский

У Вас написано:

ls -dt1 `grep -il отчет *` | head -1

если знания по шелу мне не изменяют, то должно быть:

ls -dt | `grep -il отчет *` | head -1