Чтение онлайн

на главную - закладки

Жанры

UNIX — универсальная среда программирования
Шрифт:

В гл. 3 цикл

for
использовался для нескольких итеративных программ. Обычно цикл
for
охватывает множество имен файлов, как в
'for i in * .с'
, или все аргументы командного файла, как в
'for i in $*'
. Но циклы в языке
shell
могут быть более общими, чем в этих идиомах, например цикл
for
в команде
which
.

Имеются три вида циклов:

for
,
while
и
until
. Чаще всего используется цикл
for
. В нем выполняется последовательность команд (тело цикла) для каждого элемента из множества слов. В большинстве случаев множество образуют просто имена файлов. В циклах
while
и
until
контроль над выполнением тела цикла осуществляется с помощью кода завершения команды. Тело цикла выполняется до тех пор, пока команда условия не вернет ненулевой код для
while
или нуль для
until
. Циклы
while
и
until
идентичны, за исключением кода завершения команды.

Ниже приведены основные формы каждого цикла:

for i in список слов

do

 тело цикла, $i последовательно получает значения элементов

done

for i (явно перечисляются аргументы командного файла, т.е. $*)

do

 тело цикла, $i последовательно получает значения аргументов

done

while команда

do

 тело цикла выполняется, пока команда возвращает истина

done

until команда

do

 тело цикла выполняется, пока команда возвращает ложь

done

Вторая форма цикла

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

Командой условия, управляющей циклами

while
или
until
, может быть любая команда. Очевидным примером служит цикл
while
, в котором осуществляется контроль входа (пусть Мэри) в систему:

while sleep 60

do

 who | grep mary

done

Команда

sleep
, устанавливающая паузу на 60 с, всегда выполняется нормально (если ее не прервали) и, значит, всегда возвращает код "успех", поэтому в цикле раз в минуту будет проверяться, находится ли Мэри в системе. Недостаток такого решения состоит в том, что если Мэри уже вошла в систему, то нужно ждать 60 с, чтобы узнать об этом. О продолжении же работы Мэри в системе каждую минуту будет поступать сообщение. Цикл можно перевернуть и записать с помощью
until
, чтобы получать информацию сразу без задержки, если Мэри в данный момент работает в системе:

until who | grep mary do

 sleep 60

done

Теперь условие представляется более интересным. Если Мэри вошла в систему, то

'who | grep mary'
выдаст запись о ней из списка команды
who
и вернет код "истина". Это связано с тем, что
grep
выдает код завершения, показывающий, удалось ли ей найти что-нибудь, а код завершения конвейера есть код завершения последней команды.

В заключение мы можем оформить команду, дав ей имя и установив в системе:

$ cat watchfor

# watchfor: watch for someone to log in

PATH=/bin:/usr/bin case $# in

0) echo 'Usage: watchfor person' 1>&2; exit 1

esac

until who | egrep "$1"

do

 sleep 60

done

$ cx watchfor

$ watchfor you

you tty0 Oct 1 08:01
Работает

$ mv watchfor /usr/you/bin
Установим в системе

$

Мы заменили

grep
на
egrep
, чтобы было можно задавать

$ watchfor 'joe | mary'

и следить за несколькими пользователями.

Более сложный пример: можно контролировать вход в систему и выход из нее всех пользователей и сообщать обо всех фактах входа или выхода. Это можно рассматривать как некоторое дополнение к команде

who
. Основная идея проста: раз в минуту запускать команду
who
и сравнивать результат ее действия с результатом, полученным минутой ранее, сообщая обо всех различиях. Вывод команды
who
хранится в файле, и мы можем записывать его в каталог
/tmp
. Чтобы отличить свои файлы от файлов, принадлежащих другим процессам, в имена файлов вставляется переменная интерпретатора
$$
(номер процесса команды интерпретатора), что является обычной практикой. Имя команды упоминается во временных файлах главным образом для администратора системы. Часто команды (включая данную версию
watchfor
) оставляют после себя файлы в /tmp, и полезно знать, какая команда это сделала. Здесь
":"
— встроенная команда, которая

$ cat watchwho

# watchwho: watch who logs in and out

PATH=/bin:/usr/bin

new=/tmp/wwho1.$$

old=/tmp/wwho2.$$

> $old # create an empty file

while : # loop forever

do

 who >$new

 diff $old $new

 mv $new $old

 sleep 60

done | awk '/>/ { $1 = "in: "; print }

/</ { $1 = "out: "; print }'

$

только обрабатывает свои аргументы и возвращает код "истина". Мы могли бы заменить ее командой

true
, просто передающей код завершения "истина" (есть также команда
false
), но команда
':'
более эффективна, поскольку не нужно выполнять эту команду, выбирая ее из файловой системы.

В выводе команды

diff
используются символы
<
и
>
для разделения данных из двух файлов. Программа, написанная на языке
awk
, обрабатывает результаты, чтобы сообщить об изменениях в более понятном формате. Обратите внимание на то, что весь цикл передает результаты работы по конвейеру
awk
программе, вместо того, чтобы запускать заново
awk
программу каждую минуту. Для такой обработки редактор
sed
не подходит, поскольку его вывод всегда задерживается по сравнению с входным потоком на одну строку: всегда есть одна входная строка, которая уже обработана, но не напечатана, а это приводит к ненужной задержке.

Поскольку файл

old
создается пустым, первый вывод команды
watchfor
содержит весь список пользователей, находящихся в системе в данный момент. Замена команды, которая создает файл
old
, на
who > $old
приведет к тому, что
watchfor
выдаст только изменения, но это уже — дело вкуса.

Другая программа в цикле следит за содержимым вашего почтового ящика: как только оно изменяется, программа выдает сообщение: "You have a mail" ("У вас есть почта"). Такая программа является полезной альтернативой встроенному в интерпретатор механизму, использующему переменную

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

Поделиться:
Популярные книги

Гром из трущоб

Мазуров Дмитрий
6. Громовая поступь
Фантастика:
фэнтези
рпг
6.00
рейтинг книги
Гром из трущоб

Газлайтер. Том 17

Володин Григорий Григорьевич
17. История Телепата
Фантастика:
боевая фантастика
попаданцы
аниме
5.00
рейтинг книги
Газлайтер. Том 17

Мужество

Кетлинская Вера Казимировна
Проза:
советская классическая проза
7.56
рейтинг книги
Мужество

Цикл романов "Целитель". Компиляция. Книги 1-17

Большаков Валерий Петрович
Целитель
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Цикл романов Целитель. Компиляция. Книги 1-17

Монстр из прошлого тысячелетия

Еслер Андрей
5. Соприкосновение миров
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Монстр из прошлого тысячелетия

Ермак. Телохранитель

Валериев Игорь
2. Ермак
Фантастика:
альтернативная история
7.50
рейтинг книги
Ермак. Телохранитель

Геррон

Левински Шарль
Проза:
современная проза
7.71
рейтинг книги
Геррон

Дважды одаренный. Том III

Тарс Элиан
3. Дважды одаренный
Фантастика:
альтернативная история
аниме
фэнтези
фантастика: прочее
юмористическое фэнтези
5.25
рейтинг книги
Дважды одаренный. Том III

Виктор Глухов агент Ада. Компиляция. Книги 1-15

Сухинин Владимир Александрович
Виктор Глухов агент Ада
Фантастика:
фэнтези
героическая фантастика
боевая фантастика
попаданцы
5.00
рейтинг книги
Виктор Глухов агент Ада. Компиляция. Книги 1-15

Третий. Том 6

INDIGO
Вселенная EVE Online
Фантастика:
боевая фантастика
космическая фантастика
фантастика: прочее
попаданцы
5.00
рейтинг книги
Третий. Том 6

Вернувшийся: Посол. Том IV

Vector
4. Вернувшийся
Фантастика:
космическая фантастика
киберпанк
5.00
рейтинг книги
Вернувшийся: Посол. Том IV

Кодекс Охотника. Книга XVII

Винокуров Юрий
17. Кодекс Охотника
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Кодекс Охотника. Книга XVII

Пламенев. Книга 3-7

Карелин Сергей Витальевич
Пламенев
Фантастика:
аниме
уся
фэнтези
сянься
5.00
рейтинг книги
Пламенев. Книга 3-7

Убивая маску

Метельский Николай Александрович
13. Унесенный ветром
Фантастика:
боевая фантастика
5.75
рейтинг книги
Убивая маску