Поскольку файл old
создается пустым, первый вывод команды watchfor
содержит весь список пользователей, находящихся в системе в данный момент. Замена команды, которая создает файл old
, на who > $old
приведет к тому, что watchfor
выдаст только изменения, но это уже — дело вкуса.
Другая программа в цикле следит за содержимым вашего почтового ящика: как только оно изменяется, программа выдает сообщение: "You have a mail" ("У вас есть почта"). Такая программа является полезной альтернативой встроенному в интерпретатор механизму, использующему переменную MAIL
. Чтобы показать другой стиль программирования, мы реализовали ее с помощью переменных интерпретатора, а не файлов:
$ cat checkmail
# checkmail: watch mailbox for growth
PATH=/bin:/usr/bin
MAIL=/usr/spool/mail/`getname` # system dependent
t=${1-60}
x="`ls -l $MAIL`"
while :
do
y="`ls -l $MAIL`"
echo $x $y
x="$y"
sleep $t
done | awk '$4 < $12 { print "You have mail" }'
$
Мы опять воспользовались awk
программой, на этот раз — чтобы добиться вывода сообщения только в тех случаях, когда почтовый ящик пополняется, а не просто изменяется. Иначе вы получите сообщение сразу после исключения письма. (Версия, встроенная в интерпретатор, имеет такой недостаток.)
Обычно интервал времени устанавливается равным 60 с, но если командная строка содержит параметр, например
$ chekmail 30
то интервал задается им. Переменная интерпретатора принимает в качестве значения заданное параметрами время или 60 с, если время не задано, с помощью присваивания
t=${1-60}
Это еще одна возможность языка shell
. ${var}
эквивалентно $var
и может использоваться для преодоления трудностей, связанных с появлением переменных внутри буквенно-цифровых строк:
$ var=hello
$ varx=goodbye
$ echo $var
hello
$ echo ${var}x
hellox
$
Определенные символы внутри фигурных скобок задают специальную обработку переменной. В том случае, когда переменная не определена и за ее именем идет знак вопроса, выдается строка, следующая за символом ?
, и интерпретатор прекращает работу (если только он не работает в диалоговом режиме). При отсутствии строки печатается стандартное сообщение:
$ echo ${var?}
hello
все в порядке, var определено
$ echo ${junk}
junk: parameter not set
стандартное сообщение
$ echo ${junk?error!}
junk: error!
строка задана
$
Отметим, что в сообщении, выдаваемом интерпретатором, всегда указывается имя неопределенной переменной.
В другой конструкции ${var-thing}
выбирается $var
, если оно определено, и thing
— в противном случае. В подобной конструкции ${var-thing}
значение $var
также устанавливается равным thing
:
$ echo ${junk-'Hi there'}
Hi there
$ echo ${junk?)
junk: parameter not set
значение junk не изменилось
$ echo {junk='Hi there'}
Hi there
$ echo ${junk?}
Hi there
junk принял значение Hi there
$
Правила получения значений переменных приведены в табл. 5.3. Возвращаясь к нашему исходному примеру
t=${1-60}
видим, что t
присваивается $1
или 60, если аргумент не задан.
$var |
Значение var ; ничего, если var не определено |
${var} |
То же; полезно, если за именем переменной следует буквенно-цифровая строка |
${var-thing} |
Значение var , если оно определено; в противном случае — thing ; $var не изменяется |
${var=thing} |
Значение var , если оно определено; в противном случае — thing . Если var не определено, то $var присваивается thing |
${var?строка} |
Если var определено — $var ; в противном случае выводится строка и интерпретатор прекращает работу. При пустой строке выводится: var: parameter not set |
${var+thing} |
thing , если $var определено; в противном случае — ничего |
Таблица 5.3: Получение значений переменных в языке
Упражнение 5.9
Обратите внимание на реализацию команд true
и false
в /usr/bin
или /bin
. (Как бы вы определили, где они находятся?)
Упражнение 5.10
Измените команду watchfor
так, чтобы пользователь мог задавать несколько имен, а не вводить 'joe|mary'
.
Упражнение 5.11
Напишите версию команды watchwho
, которая использует команду comm
вместо awk
для сравнения новой и старой информации. Какая версия вам больше нравится?
Читать дальше
Конец ознакомительного отрывка
Купить книгу