|
Previous | Содержание | Next ВВЕДЕНИЕ В UNIX7. ПРОГРАММИРОВАНИЕ В ЯЗЫКЕ SHELL7.1. Версии Shell Shell - интерпретатор команд, подаваемых с терминала или из командного файла. Это обычная программа (т.е. не входит в ядро операционной системы UNIX). Ее можно заменить на другую или иметь несколько. Две наиболее известные версии: - Shell (версии 7 UNIX) или Bourne Shell (от фамилии ав- тора S.R.Bourne из фирмы Bell Labs) [5]; - C-Shell (версии Berkley UNIX). Они похожи, но есть и отличия: C-Shell мощнее в диалого- вом режиме, а обычный Shell имеет более элегантные управляю- щие структуры. Shell - язык программирования, так как имеет:
7.2. Файл начала сеанса (login - файл) Независимо от версии Shell при входе в систему UNIX ищет файл начала сеанса с предопределенным именем, чтобы выпол- нить его как командный файл;
В этот файл обычно помещают команды:
7.3. Процедура языка Shell Это командный файл. Два способа его вызова на выполнение:
-rwxr-xr-x) $ dothat. Следует знать порядок поиска каталогов команд (по умолча- нию):
Следовательно, если имя вашего командного файла дублирует имя команды в системных каталогах, последняя станет недос- тупной (если только не набирать ее полного имени). 7.4. Переменные Shell В языке Shell версии 7 определение переменной содержит имя и значение: var = value. Доступ к переменной - по имени со знаком $ спереди: fruit = apple (определение); echo $fruit (доступ); apple (результат echo). Таким образом, переменная - это строка. Возможна конкате- кация строк: $ fruit = apple $ fruit = pine$fruit $ echo $fruit pineapple $ fruite = apple $ wine = ${fruite}jack $ echo $wine applejack $ Другие способы установки значения переменной - ввод из файла или вывод из команды (см. раздел 7.6), а также присва- ивание значений переменной - параметру цикла for из списка значений, заданного явно или по умолчанию (см. раздел 7.9). Переменная может быть:
$ S = "sort + 2n + 1 - 2" (наличие пробелов требует кавы- чек "") $ $S tennis/lpr $ $S basketball/lpr $ $S pingpong/lpr $ Однако внутри значения для команды не могут быть символы |, >, <, & (обозначающие канал, перенаправления и фоновый режим). 7.5. Предопределенные переменные Shell Некоторые из них можно только читать. Наиболее употреби- тельные: HOME - "домашний" каталог пользователя; служит аргументом по умолчанию для cd; PATH - множество каталогов, в которых UNIX ищет команды; PS1 - первичная подсказка (строка) системы (для v.7 - $). Изменение PS1 (подсказки) обычно делается в login - фай- ле, например: PS1 = ? или PS1 = "? " (с пробелом, что удобнее). Изменение PATH: $ echo $PATH - посмотреть; :/bin:/usr/bin - значение PATH; $ cd - "домой"; $ mkdir bin - новый каталог; $ echo $HOME - посмотреть; /users/maryann - текущий каталог; $ PATH = :$HOME/bin:$PATH - изменение PATH; $ echo $PATH - посмотреть; :/users/maryann/bin:/bin:/usr/bin - новое значение PATH. 7.6. Установка переменной Shell выводом из команды Пример 1: $ now = `date` (где `` - обратные кавычки) $ echo $now Sun Feb 14 12:00:01 PST 1985 $ Пример 2: (получение значения переменной из файла): $ menu = `cat food` $ echo $menu apples cheddar chardonnay (символы возврата каретки за- меняются на пробелы). 7.7. Переменные Shell - аргументы процедур Это особый тип переменных, именуемых цифрами. Пример: $ dothis grapes apples pears (процедура). Тогда позиционные параметры (аргументы) этой команды дос- тупны по именам: $1 = `grapes` $2 = `apples` $3 = `pears` и т.д. до $9. Однако есть команда shift, которая сдвигает имена на остальные аргументы, если их больше 9 (окно шириной 9). Другой способ получить все аргументы (даже если их больше 9): $*, что эквивалентно $1$2 ... Количество аргументов присваивается другой переменной: $#(диез). Наконец, имя процедуры - это $0; переменная $0 не учитывается при подсчете $#. 7.8. Структурные операторы Shell Кроме процедур, в языке Shell имеются структурные опера- торы типа "if-else" и "while-do". Программирование на Shell, кроме написания процедур, используется для: - отработки алгоритма перед кодированием его в языках С или ФОРТРАН-77 (нет компиляции, линкирования, загрузки, простота отладки); - обучения принципам программирования непрограммистов. 7.9. Оператор цикла for Пусть имеется командный файл makelist (процедура) $ cat makelist sort +1 -2 people | tr -d -9 | pr -h Distribution | lpr. Если вместо одного файла people имеется несколько, нап- ример: adminpeople, hardpeople, softpeople,..., то необходимо повторить выполнение процедуры с различными файлами. Это возможно с помощью for - оператора. Синтаксис: for <переменная> in <список значений> do <список команд> done Ключевые слова for, do, done пишутся с начала строки. Пример (изменим процедуру makelist) for file in adminpeople, hardpeople, softpeople do Sort +1 -2 $file | tr ... | lpr done. Можно использовать метасимволы Shell в списке значений. Пример: for file in *people (для всех имен, кончающихся на people) do ... done. Если in опущено, то по умолчанию в качестве списка значе- ний берется список аргументов процедуры, в которой содержит- ся цикл, а если цикл не в процедуре, то - список параметров командной строки (то есть в качестве процедуры выступает ко- манда). Пример: for file do ... done Для вызова makelist adminpeople hardpeople softpeople бу- дет сделано то же самое. 7.10. Условный оператор if Используем имена переменных, представляющие значения па- раметров процедуры: sort +1 -2 $1 | tr ... | lpr Пример неверного вызова: makelist (без параметров), где $1 неопределен. Исправить ошибку можно, проверяя количество аргументов - значение переменной $# посредством if - оператора. Пример: (измененной процедуры makelist): if test $# -eq 0 then echo "You must give a filename" exit 1 else sort +1 -2 $1 | tr ... | lpr fi Здесь test и exit - команды проверки (см. раздел 7.11) и выхода. Таким образом, синтаксис оператора if: if <если эта команда выполняется успешно, то>; then <выполнить все следующие команды до else или, если его нет, до fi>; [else <иначе выполнить следующие команды до fi>] Ключевые слова if, then, else и fi пишутся с начала строки. Успешное выполнение процедуры означает, что она возвраща- ет значение true = 0 (zero) (неуспех - возвращаемое значение не равно 0). Оператор exit 1 задает возвращаемое значение 1 для неу- дачного выполнения makelist и завершает процедуру. Возможны вложенные if. Для else if есть сокращение elif, которое одновременно сокращает fi. 7.11. Команда "test" Не является частью Shell, но применяется внутри Shell- процедур. Имеется три типа проверок:
Для каждого типа свои примитивы (операции op). Для чисел синтаксис такой: N op M, где N, M - числа или числовые переменные; op принимает значения: -eq, -ne, gt, -lt, -ge, -le (с обычным смыслом, как, например, в ФОРТРАН). Для файла синтаксис такой: op filename, где op принимает значения: -s (файл существует и не пуст); -f (файл, а не каталог); -d (файл-директория (каталог); -w (файл для записи); -r (файл для чтения). Для строк синтаксис такой: S op R, где S, R - строки или строковые переменные или op1 S op принимает значения: = (эквивалентность); != (не эквивалентность); op1 принимает значения: -z (строка нулевой длины); -n (не нулевая длина строки). Наконец, несколько проверок разных типов могут быть объ- единены логическими операциями -a (AND) и -o (OR). Примеры: $ if test -w $2 -a -r S1 > then cat $1 >> $2 > else echo "cannot append" > fi $ В некоторых вариантах ОС UNIX вместо команды test исполь- зуются квадратные скобки, т.е. if [...] вместо if test ... . 7.12. Оператор цикла while Синтаксис: while <команда> do <команды> done Если "команда" выполняется успешно, то выполнить "коман- ды", завершаемые ключевым словом done. Пример: if test $# -eq 0 then echo "Usage: $0 file ..." > &2 exit fi while test $# -gt 0 do if test -s $1 then echo "no file $1" > &2 else sort + 1 - 2 $1 | tr -d ... (процедуры) fi shift (* перенумеровать аргументы *) done Процедуры выполняются над всеми аргументами. 7.13. Оператор цикла until Инвертирует условие повторения по сравнению с while Синтаксис: until <команда> do <команды> done Пока "команда" не выполнится успешно, выполнять команды, завершаемые словом done. Пример: if test S# -eq 0 then echo "Usage $0 file..." > &2 exit fi until test S# -eq 0 do if test -s $1 then echo "no file $1" > &2 else sort +1 -2 $1 | tr -d ... (процедура) fi shift (сдвиг аргументов) done Исполняется аналогично предыдущему. 7.14. Оператор выбора case Синтаксис: case Пример: Пусть процедура имеет опцию -t, которая может быть подана как первый параметр: ................. together = no case $1 in -t) together = yes shift ;; -?) echo "$0: no option $1" exit ;; esac if test $together = yes then sort ... fi где ? - метасимвол (если -?, т.е. "другая" опция, отлич- ная от -t, то ошибка). Можно употреблять все метасимволы языка Shell, включая ?, *, [-]. Легко добавить (в примере) другие опции, просто расширяя case. 7.15. Использование временных файлов в каталоге /tmp Это специальный каталог, в котором все файлы доступны на запись всем пользователям. Если некоторая процедура, создающая временный файл, ис- пользуется несколькими пользователями, то необходимо обеспе- чить уникальность имен создаваемых файлов. Стандартный прием - имя временного файла $0$$, где $0 - имя процедуры, а $$ - стандартная переменная, равная уникальному идентификационно- му номеру процесса, выполняющего текущую команду. Хотя администратор периодически удаляет временные файлы в /tmp, хорошей практикой является их явное удаление после ис- пользования. 7.16. Комментарии в процедурах Они начинаются с двоеточия :, которое считается нуль-ко- мандой, а текст комментария - ее аргументом. Чтобы Shell не интерпретировал метасимволы ($, * и т.д.), рекомендуется заключать текст комментария в одиночные кавычки. В некоторых вариантах ОС UNIX примечание начинается со знака #. 7.17. Пример процедуры :'Эта процедура работает с файлами, содержащими имена' : 'и номера телефонов,' :'сортирует их вместе или порознь и печатает результат на' :'экране или на принтере' :'Ключи процедуры:' :'-t (together) - слить и сортировать все файлы вместе' :'-p (printer) - печатать файлы на принтере' if test $# - eq 0 then echo "Usage: $ 0 file ... " > & 2 exit fi together = no print = no while test $# -gt 0 do case $1 in -t) together = yes shift ;; -p) print = yes shift ;; -?) echo "$0: no option $1" exit ;; *) if test $together = yes then sort -u +1 -2 $1 | tr ... > /tmp/$0$$ if $print = no then cat /tmp/$0$$ else lpr -c /tmp/$0$$ fi rm /tmp/$0$$ exit else if test -s $1 then echo "no file $1" > &2 else sort +1 -2 $1 | tr...> /tmp/$0$$ if $print = no then cat /tmp/$0$$ else lpr -c /tmp/$0$$ fi rm /tmp/$0$$ fi shift fi;; esac done. Процедура проверяет число параметров $#, и если оно равно нулю, завершается. В противном случае она обрабатывает пара- метры (оператор case). В качестве параметра может выступать либо ключ (символ, предваряемый минусом), либо имя файла (строка, представленная метасимволом *). Если ключ отличен от допустимого (метасимвол ? отличен от t и p), процедура завершается. Иначе в зависимости от наличия ключей t и p вы- полняются действия, заявленные в комментарии в начале проце- дуры. 7.18. Обработка прерываний в процедурах Если при выполнении процедуры получен сигнал прерывания (от клавиши BREAK или DEL, например), то все созданные вре- менные файлы останутся неудаленными (пока это не сделает ад- министратор) ввиду немедленного прекращения процесса. Лучшим решением является обработка прерываний внутри про- цедуры оператором trap: Синтаксис: trap 'command arguments' signals... Кавычки формируют первый аргумент из нескольких команд, разделенных точкой с запятой. Они будут выполнены, если воз- никнет прерывание, указанное аргументами signals (целые): 2 - когда вы прерываете процесс; 1 - если вы "зависли" (отключены от системы) и др. Пример (развитие предыдущего): case $1 in ..... *) trap 'rm /tmp/*; exit' 2 1 (удаление временных файлов) if test -s $1 .............. rm /tmp/* Лучше было бы: trap 'rm /tmp/* > /dev/null; exit' 2 1 так как прерывание может случиться до того, как файл /tmp/$0$$ создан и аварийное сообщение об этом случае пере- направляется на null-устройство. 7.19. Выполнение арифметических операций: expr Команда expr вычисляет значение выражения, поданного в качестве аргумента и посылает результат на стандартный вы- вод. Наиболее интересным применением является выполнение операций над переменными языка Shell. Пример суммирования 3 чисел: $ cat sum3 expr $1 + $2 + $3 $ chmod 755 sum3 $ sum3 13 49 2 64 $ Пример непосредственного использования команды: $ expr 13 + 49 + 2 + 64 + 1 129 $ В expr можно применять следующие арифметические операто- ры: +, -, *, /, % (остаток). Все операнды и операции должны быть разделены пробелами. Заметим, что знак умножения следует заключать в кавычки (одинарные или двойные), например: '*', так как символ * имеет в Shell специальный смысл. Более сложный пример expr в процедуре (фрагмент): num = 'wc -l < $1' tot = 100 count = $num avint = 'expr $tot / $num' avdec = 'expr $tot % $num' while test $count -gt 0 do ... Здесь wc -l осуществляет подсчет числа строк в файле, а да- лее это число используется в выражениях. 7.20. Отладка процедур Shell Имеются три средства, позволяющие вести отладку процедур.
Previous | Содержание | Next |
|||||||||||||||||
With any suggestions or questions please feel free to contact us |