Программирование на shell (UNIX), часть 3

		4.5. Параметры

     В  командный  файл  могут  быть  переданы параметры. В shell

используются  позиционные параметры (т.е. существенна очередность

их  следования).  В  командном  файле  соответствующие параметрам

переменные  (аналогично  shell-переменным)  начинаются  с символа

"$", а далее следует одна из цифр от 0 до 9:

     Пусть  расчет  "examp-1"  вызывается  с параметрами "cock" и

"tail".  Эти  параметры  попадают  в новую среду под стандартными

именами  "1" и "2". В (стандартной) переменной с именем "0" будет

храниться имя вызванного расчета.

     При  обращении  к  параметрам  перед  цифрой ставится символ

доллара "$" (как и при обращении к переменным):

     $0 - соответствует имени данного командного файла;

     $1 - первый по порядку параметр;

     $2 - второй параметр и т.д.

     Пусть командный файл с именем "examp-1" имеет вид

      echo Это расчет $0:

      sort $2 >
>
 $1

      cat $1

     а файлы "cock" и "tail" содержат соответсвенно

cock:

      Это отсортированный файл:

tail:

      1

      3

      2

     Тогда после вызова команды

      examp-1 cock tail

на экране будет

     Это расчет examp-1:

     Это отсортированный файл:

     1

     2

     3

     Поскольку  число  переменных,  в  которые могут передаваться

параметры,  ограничено  одной  цифрой,  т.е.  9-ю  ("0",  как уже

отмечалось  имеет  особый  смысл), то для передачи большего числа

параметров используется специальная команда "shift".

     Рассмотрим ее действие на примере.

     Пусть командный файл "many" вызывается с 13-ю параметрами

     many 10 20 30 40 50 60 70 80 90 100 110 120 130

     И имеет вид

     ###

     # many: Передача большого числа параметров.

     echo "$0: Много параметров"

     echo " Общее число параметров = $#

     Исходное состояние: $1 $5 $9 "

     shift

     echo "1 сдвиг: первый=$1 пятый=$5 девятый=$9"

     shift 2

     echo "1 + 2 = 3 сдвига: первый=$1 пятый=$5 девятый=$9"

     perem=`expr $1 + $2 + $3`

     echo $perem

     В  результате  первого  применения  команды  "shift"  второй

параметр  расчета  вызывается  как $1, третий параметр вызывается

как  $2,  ...  десятый  параметр, который был исходно недоступен,

вызывается как $9. Но стал недоступным первый параметр!

     После выполнения этого расчета на экране будет:

     many: Много параметров

     Общее число параметров = 13

     Исходное состояние: 10 50 90

     1 сдвиг: первый=20 пятый=60 девятый=100

     1 + 2 = 3 сдвиг: первый=40 пятый=80 девятый=120

     150

     Своеобразный подход к параметрам дает команда "set".

     Например, фрагмент расчета

     set a b с

     echo первый=$1 второй=$2 третий=$3

     выдаст на экран

     первый=a второй=b третий=c

     т.е.  команда  "set"  устанавливает значения параметров. Это

бывает  очень  удобно.  Например,  команда "date" выдает на экран

текущую  дату,  скажем, "Mon May 01 12:15:10 2000",  сосотящую из

пяти слов, тогда

      set `date`

      echo $1 $3 $5

      выдаст на экран

      Mon 01 2000

     Команда   "set"   позволяет   также   осуществлять  контроль

выполнения программы, например:

     set -v - на терминал выводятся строки, читаемые shell.

     set +v - отменяет предыдущий режим.

     set -x - на терминал выводятся команды перед выполнением.

     set +x - отменяет предыдущий режим.

     Команда  "set"  без параметров выводит на терминал состояние

программной среды (см далее).

	       4.6. Подстановки shell-интерпретатора

     Перед  началом  непосредственной интерпретации и выполнением

команд,   содержащихся   в   командных  файлах,  shell  выполняет

различные виды подстановок:

     1.   ПОДСТАНОВКА   РЕЗУЛЬТАТОВ.   Выполняются  все  команды,

заключенные  в  обратные  кавычки,  и  на  их место подставляется

результат.

     2.  ПОДСТАНОВКА  ЗНАЧЕНИЙ  ПАРАМЕТРОВ  И ПЕРЕМЕННЫХ. То есть

слова, начинающиеся на "$", заменяются соответсвующими значениями

переменных и параметров.

     3.    ИНТЕРПРЕТАЦИЯ   ПРОБЕЛОВ.   Заэкранированные   пробелы

игнорируются.

     4. ГЕНЕРАЦИЯ ИМЕН ФАЙЛОВ. Проверяются слова на наличие в них

спецсимволов   ("*", "?","[]")   и  выполняются    соответсвующие

генерации.

		  4.7. Программная среда

     Каждый  процесс имеет среду, в которой он выполняется. shell

использует ряд переменных этой среды.

     Если  вы  наберете команду "set" без параметров, то на экран

будет  выдана информация о ряде стандартных переменных, созданных

при  входе  в  систему  (и  передаваемых  далее  всем вашим новым

процессам  "по  наследству"),  а  также  переменных,  созданных и

экспортируемых вашими процессами.

     Конкретный  вид и содержание выдаваемой информации в немалой

степени зависит от того, какая версия UNIX используется и как

инсталлирована система.

     Вот лишь часть того, что выдала мне команда "set":

     HOME=/home/sae

     PATH=/usr/local/bin:/usr/bin:/bin:.:/usr/bin/X11:

     IFS=

     LOGNAME=sae

     MAIL=/var/spool/mail/sae

     PWD=/home/sae/STUDY/SHELL

     PS1=${PWD}:" "

     PS2=>

     SHELL=/bin/bash

     TERM=linux

     TERMCAP=console|con80x25|dumb|linux:li#25:co#80::

     UID=501

     perem=stroka

     x=5

     Прокомментируем эти присваивания значений переменным.

     HOME=/home/sae  -  это  имя  домашнего директория, в котором

пользователь  (в  данном  случае  я)  оказывается  после  входа в

систему.  То  есть,  правильно  набрав  имя и пароль, я окажусь в

директории "/home/sae".

     PATH=/bin:/usr/bin:.:/usr/local/bin:/usr/bin/X11    -    эта

переменная  задает  последоватьельность  файлов  (ТРОПУ), которые

просматривает "shell" в поисках команды. Имена файлов разделяются

здесь  двоеточиями.  Последовательность  просмотра  соответствует

очередности  следования  имен  в  тропе.  НО  ПЕРВОНАЧАЛЬНО поиск

происходит  среди  так  называемых  встроенных  команд.  В  число

встроенных  команд  входят  наиболее  часто используемые команды,

например   "echo",  "cd",  "pwd",  "date".  После  этого  система

просматривает   директорий  "/bin",  в  котром  могут  находиться

команды "sh", "cp", "mv", "ls" и т.п. Затем директорий "/usr/bin"

с  командами  "cat",  "сс",  "expr",  "nroff",  "man"  и  многими

другими.  Далее  поиск  происходит в текущем директории (".", или

другое обозначение - "пусто", т.е.""), где скорее всего находятся

написанные вами команды (расчеты).

     После  набора  командной  строки  и  нажатия

 "shell"

(после   выполнения   необходимых  подстановок)  распознает  имя,

соответстующее  команде  и  осуществляеет ее поиск в директориях,

перечисленных   в   тропе.   Если   команда  размещена  вне  этих

директориев  -  она не будет найдена. Если присутствует несколько

команд   с  одинаковым  именем,  то  вызвана  будет  та,  которая

расположена в директории, просматриваемом первым.

     Тропу, как и прочие перемнные, можно легко менять, добавляя,

переставляя  или  исключая  директории.  (Кстати,  представленная

тропа получена из "настоящей" путем сокращений и перестановок).

     IFS=   - (Внутренний Разделитель Полей) перечисляет символы,

которые  служат  для  разделения  слов (полей). Таковыми являются

"пробел",  "табуляция" и "перевод строки", поэтому здесь слева от

присваивания ничего не видно и занято две строки.

     LOGNAME=sae  - имя входа ("имя" пользователя).

     MAIL=/var/spool/mail/sae  -  имя  файла, в который поступает

(электронная) почта.

     PWD=/home/sae/STUDY/SHELL  - имя текущего директория

     PS1=${PWD}:" "   - вид промтера. В данном случае в промптере

будет  выдаваться  имя текущего директория двоеточие и пробел. То

есть здесь будет "/home/sae/STUDY/SHELL: ".

     PS2=>
   -   этот   промтер   (эдесь  ">
")  используется  как

приглашение    к   продолжению   ввода   (в   очередной   строке)

незаконченной  команды. Например, наберите открывающую скобку "("

и  после  нажатия

  в  следующей  строке  вы увидите этот

промптер.  Если  пока  не  знаете,  что  дальше  делать, наберите

закрывающую скобку ")" - и он исчезнет.

     SHELL=/bin/bash - эта переменная указывает оболочку, которую

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

(стандартный)  shell  ("sh"),  а  "продвинутая"  версия - "bash",

написанная тем же автором (Bourne-Again SHell).

     TERM=linux - указание типа терминала.

     TERMCAP=console|con80x25|dumb|linux:li#25:co#80::          -

(TERMinal  CAPacity) это (очень сильно) обрезанная строка задания

параметров терминала.

     UID=501       -  идентификатор пользователя (мой - "501").

     perem=stroka

     x=5          - переменные, которые ввел пользователь.

     Исходная  среда  устанавливается  автоматически  при входе в

систему с использованием файлов типа "/etc/rc" и "/etc/.profile".

     ВАЖНОЕ  ЗАМЕЧАНИЕ.  Один  из  способов  просто изменит среду

(например,  тропу поиска команд, вид промтера, вид оболочки, цвет

экрана  и  т.п.) можно, разместив эту информацию в своем домашнем

директории     в     специальизированном     файле     ".profile"

(${HOME}/.profile), присвоив нужные значения переменным среды. То

есть  вызвать  это  файл  в  редактор и написать, что пожелаете).

Тогда   при   каждом  вашем  входе  в  систему  этот  файл  будет

автоматически  выполняться и устанавливать новую среду. Этот файл

должен   ОБЯЗАТЕЛЬНО  размещаться  в  вашем  ДОМАШНЕМ  директории

(директории входа).

     Если  вы внесли изменения в ".profile", то для переноса этих

изменений в среду необходимо выполнить этот файл. Для этого можно

выйти   и   заново  войти  в  систему,  а  можно  воспользоваться

(специально  для  этого случая созданной) командой "." без выхода

из системы, т.е.

     . .profile

     Следует  иметь  в  виду,  что  имена  файлов, начинающиеся с

точки,  вообще имеют особый статус. Так, они не выдаются на экран

простой  командой "ls" - необходимо вызывать эту команду с флагом

"-a". Кстати, и не уничтожаются огульно командой "rm *".

     Дописать  новый  совй  директорий "my" в тропу команд можно,

записав в ".profile", например

     PATH=${PATH}:/home/sae/my

или

     PATH=${PATH}:${HOME}/my

     Как   правило,   устанавливаемые  переменные  среды  следует

экспортировать. Например,

     export TERM PATH REDKEYS MAIL

     Кроме  определения  переменных  в ".profile" можно выполнить

команды, например команда

      stty -lcase

установит терминал в режим "большие и маленькие буквы"; а команда

      cat заставка

     выдаст  на  экран  заставку  , которую вы сами подготовите в

файле  "заставка"  с  учетом  ваших  эстетических  пристрастий  и

художественных способностей.

     Сам  интерпретатор  shell автоматически присваивает значения

следующим переменным (параметрам):

     ?  - значение, возвращенное последней командой;

     $  - номер процесса;

     !  - номер фонового процесса;

     #  - число позиционных параметров, передаваемых в shell;

     *  - перечень параметров, как одна строка;

     @  - перечень параметров, как совокупность слов;

     -  - флаги, передаваемые в shell.

     При  обращении к этим переменным (т.е при использовании их в

командном файле - shell-программе) следует впереди ставить "$".

     Пример. Вызов расчета

     specific par1 par2 par3

     имеющего вид

     ###

     # specific: Специальные параметры (переменные)

     echo $0 - имя расчета

     echo $? - код завершения

     echo $$ - идентификатор последнего процесса

     echo $! - идентификатор последнего фонового процесса

     echo

     echo $* - значения параметров, как строки

     echo $@ - значения параметров, как слов

     echo

     set -au

     echo $- - режимы работы интерпретатора

     Выдаст на экран

     specific - имя расчета

     0 - код завершения

     499 - идентификатор последнего процесса

     98 - идентификатор последнего фонового процесса

     par1 par2 par3 - значения параметров, как строки

     par1 par2 par3 - значения параметров, как слов

     au - режимы работы интерпретатора

     Код  "0" соответсвует нормальному завершению процесса.

     Важную   роль   при   создании   уникальных   файлов  играет

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

номеру процесса, выполняющего данный расчет. Каждый новый расчет,

выполняемый компьютером, инициирует один или несколько процессов,

автоматически  получающих  номера  по-порядку. Поэтому, используя

номер  процесса в качестве имени файла, можно быть уверенным, что

каждый  новый  файл  будет иметь новое имя (не запишется на место

уже  существующего).  Достоинство  является и главным недостатком

такого  способа  именования файлов. Неизвестно, какие имена будут

присвоены  файлам.  И, если в рамках данного процесса можно найти

файл "не глядя", т.е., обратившись к нему, используя $$, то потом

такие  файлы  можно  легко  потерять.  Это создает дополнительные

проблемы при отладке программ.

     "echo" без параметров выводит пустую строку.

     Различия  $*  и $@ состоит в том, что певая переменная может

быть  представлена  как

     "par1  par2  par3"

а вторая как

     "par1" "par2" "par3"

     Пример, иллюстрирующий различия "$*" и "$@" будет рассмотрен

в связи с оператором "for".

     Для   иллюстрации   мы   установили  командой  "set"  режимы

интерпретатора  ("a" - все последующие переменные экспортируются;

"u"  -  отсутствие параметра считать ошибкой), что и отразилось в

специальной переменной "$-".

		  5. ПРОГРАММНЫЕ  СТРУКТУРЫ

     Как во всяком языке программирования в тексте на языке shell

могут  быть  комментарии. Для этого используется символ "#". Все,

что  находится  в строке (в командном файле) левее этого символа,

воспринимается интерпретатором как комментарий. Например,

     # Это комментарий.

     ## И это.

     ### И это тоже.

     Как  во  всяком  процедурном  языке программирования в языке

shell   есть   операторы.   Ряд  операторов  позволяет  управлять

последовательностью  выполнения  команд. В таких операторах часто

необходима  проверка  условия,  которая  и определяет направление

продолжения вычислений.