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