146

            9.   СРЕДСТВА ПРОГРАММИРОВАНИЯ SHELL

     Вы можете использовать  shell  для  создания  программ.
Такие программы называются также процедурами shell.  В  этом
разделе рассказывается как создавать и  выполнять  программы
shell с помощью команд, переменных, позиционных  параметров,
кодов возврата.
     Прежде чем создавать программы shell необходимо изучить
редактор.


     9.1.   Программы shell


     9.1.1.   Создание простых программ shell

     Начнем  описание  создания  простых   программ   shell,
которые выполняют задачи:
     - печать текущего справочника;
     - список содержимого этого справочника;
     - отображение следующих сообщений на вашем терминале:
        "This is the end of the shell program."
     С помощью редактора создайте файл dl и введите  в  него
строки:
        pwd
        ls
        echo This is the end of the shell program.
     Теперь вы имеете программу shell. Вы можете  с  помощью
cat отобразить содержимое файла:
        $ cat dl
        pwd
        ls
        echo This is the end of the shell program.
        $


     9.1.2.   Выполнение программ shell

     Выполнить shell программу вы можете с  помощью  команды
sh. Введите:
        sh dl
     Когда команда dl выполняется с помощью sh,  то  вначале
печатается  имя  пути  текущего  справочника,  потом  список
файлов в текущем справочнике и в конце комментарий: "This is
the end of the shell program."
     С  помощью  команды  chmod  вы  можете   сделать   файл
исполняемым:
        $ chmod u+x dl
        $ ls -l
        total 2
        -xw------ 1 login  login  3661  Nov  2   10:28 mbox
        -xwx----- 1 login  login    48  Nov 15   10:50 dl
        $
     Обратите внимание, что  chmod  включает  разрешение  на
выполнение (+x) для пользователя  (u).  Теперь  dl  является
исполняемой программой. Попытайтесь выполнить ее. Введите:
        dl


                            147
     9.1.3.   Создание справочника bin для исполняемых
        файлов

     Чтобы сделать shell программы доступными изо всех ваших
справочников, вы  можете  создать  справочник  bin  в  своем
регистрационном справочнике и переписать shell  программы  в
этот справочник.
     С  помощью  переменной  PATH  вы  можете  включить  ваш
справочник bin:
        PATH = $PATH:$HOME/bin

     9.1.4.   Ограничения при именовании программ shell

     shell  программе  вы  можете   дать   любое   имя,   не
совпадающее с  именами  системных  команд.  Если  имя  вашей
программы совпадает с именем  команды  системы,  то  система
будет выполнять вашу команду вместо системной.

     9.2.   Переменные

     shell программы  манипулируют  с  переменными.  В  этом
пункте обсуждаются три типа переменных:
     - позиционные параметры;
     - специальные параметры;
     - именованные переменные.


     9.2.1.   Позиционные параметры

     Позиционные  параметры  являются  переменными  в  shell
программе.  Их  значение  устанавливается   из   аргументов,
указанных в командной строке,  которая  вызывает  программу.
Позиционные параметры нумеруются и  на  них  ссылка  идет  с
помощью символа $: $1, $2, $3 и т.д.
     shell программа может  использовать  до  9  позиционных
параметров.  Если  shell  программа  вызывается  с   помощью
командной строки, подобной следующей:
        shell.prog pp1 pp2 pp3 pp4 pp5 pp6 pp7 pp8 pp9 
то  позиционному  параметру  $1  в  программе  присваивается
значение pp1, $2 - значение  pp2  и  т.д.  во  время  вызова
программы.  Чтобы  практически  рассмотреть  это   замещение
позиционных параметров,  создайте  файл  pp.  Затем  введите
команды echo в файл pp. В результате выполнения команды  cat
получим следующий вывод:
        $ cat pp
        echo The first positional parameter is: $1
        echo The second positional parameter is: $2
        echo The third positional parameter is: $3
        echo The fourth positional parameter is: $4
        $
     Если вы выполните эту  shell  программу  с  аргументами
one, two, three, four, то  получите  результат  (но  вначале
нужно сделать  shell  программу  pp  исполняемой  с  помощью
команды chmod):
        $ chmod u+x pp
        $
        $ pp one two three four
        echo The first positional parameter is: one


                            148
        echo The second positional parameter is: two
        echo The third positional parameter is: three
        echo The fourth positional parameter is: four
        $
     Команда who перечисляет всех  пользователей,  в  данный
момент зарегистрированных в системе. Можем  создать  простую
программу whoson, которая  будет  сообщать,  работает  ли  в
настоящий момент  конкретный  пользователь.  Введем  в  файл
whoson командную строку:
        who | grep $1
     Команда  who  перечисляет  всех  текущих  пользователей
системы,  а  команда   grep   осуществляет   поиск   строки,
содержащей значение, соответствующее позиционному  параметру
$1. Теперь подставим конкретное имя в качестве  аргумента  в
файле whoson,  например,  sue.  Когда  вы  зададите  команду
"whoson sue", shell программа заменит  $1  на  sue  в  вашей
программе и выполнит ее в следующем виде:
        who | grep sue
Вывод будет следующим:
        $ whoson sue
        sue     tty26      Jan 24 13:35
        $
     Если указанный пользователь sue  не  зарегистрирован  в
данный момент в системе, grep завершится неудачно  и  whoson
не будет ничего выводить на экран.
     shell позволяет указывать в  командной  строке  до  128
аргументов,  но  ссылаться  можно  не  более,   чем   на   9
позиционных   параметров.   В   следующем   пункте    описан
специальный параметр $*.

     9.2.2.   Специальные параметры

     Когда вы обращаетесь  к  программе  shell,  специальный
параметр $# содержит  число  аргументов,  с  которыми  shell
программа была вызвана. Это значение может использоваться  в
любом месте shell программы.
     Например, создайте командную строку  в  файле  get.num,
сделайте файл исполняемым и запустите команду cat:
        $ cat get.num
        echo The number of arguments is: $#
        $
     Программа просто отобразит число аргументов, с которыми
она была вызвана.
     Когда вы обращаететсь  к  shell  программе  специальный
параметр $* содержит строку со всеми аргументами, с которыми
программа была вызвана.

     9.2.3.   Именованные переменные

     В shell программе вы  можете  использовать  именованные
переменные. Значение именованной переменной вы  присваиваете
сами следующим образом:
        name_variable=value
     Обратите внимание, что ни  слева  ни  справа  от  знака
равенства нет пробелов.
     В следующем примере var1 - это имя переменной, а myname
-   значение   строки   символов,   которое    присваивается
переменной:


                            149
   Пример.
        var1=myname
     Знак $ используется перед  именем  переменной  в  shell
программе для ссылки на значение этой переменной. Если взять
предыдущий пример, то ссылка $var1 говорит shell, что  нужно
заменить  на  значение  myname  любую  встретившуюся  строку
символов $var1.
     Первый символ имени переменной должен быть  буквой  или
символом подчеркивания. Имя  переменной  может  состоять  из
букв, символов подчеркивания и  цифр.  Имена  переменных  не
должны  совпадать  с  именами  shell  команд.  Также   shell
зарезервировано несколько имен  переменных,  которые  вы  не
должны использовать для своих переменных. Ниже дано  краткое
описание этих зарезервированных имен переменных:
CDPATH - определяет путь поиска команды;
HOME - значение,  используемое  по  умолчанию  командой   cd
     (собственный справочник);
IFS - определяет разделитель  (обычно  пробел,  табуляция  и
     возврат каретки);
LOGNAME - ваше регистрационное имя;
MAIL - имена файлов, которые содержат электронную почту;
PATH - определяет   имя   пути,   используемое   shell   для
     нахождения команд;
PS1 - определяет первичную подсказку (по умолчанию $);
PS2 - определяет вторичную подсказку (по умолчанию >);
TERM - идентифицирует   тип   терминала.    Значение    этой
     переменной важно при работе с редактором vi;
TERMINFO - идентифицирует справочник,  в  котором  находится
     информация о вашем терминале;
TZ - определяет зону времени (по умолчанию EST5EDT).
     Значение этих переменных  вы  можете  определить  двумя
способами. Первый, вы можете ввести:
        echo $variable_name
     Система распечатает значение переменной  variable_name.
Второй способ: вы можете воспользоваться  командой  env  для
распечатки значений всех определенных  переменных  в  shell.
Для этого введите команду env и система выдаст  список  всех
имен переменных и их значения.

     9.2.4.   Присвоение значений переменным

     Если вы редактируете с помощью редактора vi, то знаете,
что  можно  установить  значения  переменной   TERM   вводом
следующей командной строки:
        TERM=terminal_name
        export TERM
     Это простейший способ присвоения  значения  переменной.
Существует еще несколько способов присвоения:
     - использование  команды  read  для  присвоения   ввода
переменной;
     - перенаправление  вывода  команды   в   переменную   с
использованием команды замены со  знаками  слабого  ударения
(`...`);
     - присвоение позиционного параметра переменной.

     9.2.4.1.   Использование команды read

     Общий формат команды read:


                            150
        read variable

     Значение,   присвоенное   командой   read    переменной
variable, будет заменять $variable где бы она не встречалась
в программе пользователя. Если программа  выполняет  команду
echo до команды read, то она сможет отобразить только:
        Type in ...
     Команда read будет ждать до тех пор, пока вы не введете
строку символов и нажмете клавишу , тем самым присваивая
строку переменной.
     Следующий пример  покажет  вам,  как  написать  простую
shell программу num.please,  содержащую  телефонные  номера.
Эта программа использует следующие команды:
echo - выдает подсказку для ввода фамилий клиентов;
read - присваивает вводимое значение переменной;
grep - просматривает файл list в поисках этой переменной.
     Программа будет выглядеть следующим образом:
    Пример.
        $ cat num.please
        echo Type in the list name:
        read name
        grep $name home/list
        $
     Создайте файл  list,  содержащий  несколько  фамилий  и
номеров телефонов. И теперь запустите файл num.please.
     В следующем примере приводится текст  программы  mknum,
которая  создает  список.  В  программе  mknum  используется
следующая последовательность команд:
echo - выдает подсказку для ввода имени клиента;
read - присваивает имя клиента переменной name;
echo - выдает подсказку для ввода номера телефона;
read - присваивает номер телефона переменной num;
echo - добавляет значение переменных name и num в файл list;
     Если вы хотите, чтобы вывод команды echo  добавлялся  в
конец списка, то вы должны использовать >>. Если  вы  будете
использовать >, то список будет состоять из последего номера
телефона, который вы добавили.
     С помощью команды cat отобразите  содержание  программы
mknum:
  Пример.
        $ cat mknum
        echo Type in name
        read name
        echo Type in number
        read num
        echo $name $num >> list
        $ chmod u+x mknum
        $

     9.2.4.2.   Перенаправление вывода команды в
        переменную

     Формат команды следующий:
        variable=command
     Вывод команды становится значением  переменной.  Пример
shell программы t, распечатывающей время:
        $ cat t
        time=`date | cut -c12-19`
        echo The time is: $time


                            151
        $
     Сделайте файл исполняемым и получите программу, которая
выдает время:
        $ chmod u+x t
        $ t
        The time is: 10:30
        $


     9.2.4.3.   Присвоение позиционного параметра
        переменной

     Вы можете присвоить позиционный  параметр  именованному
параметру следующим образом:
        var1=$1
     В следующем примере приведена программа simp.p, которая
присваивает позиционнный параметр переменной:
   Пример.
        $ cat simp.p
        var1=$1
        echo $var1
        $
     Также вы можете  присвоить  переменной  вывод  команды,
которая использует позиционные параметры:
        person=`who | grep $1`

     9.3.   Конструкции языка программирования shell

     Язык    программирования    shell    имеет    несколько
конструкций, которые придадут гибкость вашим программам:
     - комметнарии позволят описывать функции программы;
     - "here  document"  позволяет  вам  включать  в   shell
программы строки, которые будут перенаправляться как ввод  в
некоторые команды shell программы;
     - команда exit позволяет завершать программу  в  нужной
точке и использовать коды возврата;
     - конструкции  цикла  for,  while  позволяют  повторять
группу команд в цикле;
     - условные команды if и case выполняют  группу  команд,
если выполнилось некоторое условие;
     - команда break позволяет выполнить  безусловный  выход
из цикла.

     9.3.1.   Комментарии

     Чтобы    в    программе     разместить     комментарии,
воспользуйтесь знаком #. Если знак # стоит после команды, то
сама команда выполняется, а комментарий игнорируется. Формат
строки комментария:
        #comment


     9.3.2.   "Here document"

     "Here document" позволяет размещать в  shell  программе
строки, которые перенаправляются в качестве ввода команды  в
этой программе. Это один из способов обеспечения  ввода  для
команды  в  shell  программе  без  использования  отдельного


                            152
файла.  Запись  состоит  из  символа  перенаправления  <<  и
разделителя, который указывает начало и конец строк ввода. В
качестве разделителя может использоваться  один  символ  или
строка символов. Чаще всего это знак !.
     Формат команды следующий:
        command<
        ...input lines...
        delimiter

     9.3.3.   Использование ed в shell программе

     "Here document" предлагает способ  использования  ed  в
shell  программе.  Предположим  вы  хотите   создать   shell
программу, которая будет  вызывать  редактор  ed,  проводить
глобальные изменения в файле, записывать изменения в файл  и
затем завершать работу с ed. На следующем  экране  приведено
содержание программы ch.text, которая выполняет эти задачи:
      $ cat ch.text
      echo Type in the filename
      read file1
      echo Type in the exact text to be changed.
      read old_text
      echo Type in the exact new text to replace the above.
      read new_text
      ed - $file1 <
        Type in the filename
        memo
        Type in the exact text to be changed.
        Dear John:
        Type in the exact new text to replace the above.
        To what it may concern:
        $ cat memo
        To what it may concern:
        $

     9.3.4.   Коды завершения


                            153
     Большинство  команд  shell  возвращает  коды,   которые
указывают, успешно ли завершилась команда. Если возвращаемое
значение  0(ноль),  то  команда  выполнилась  успешно.  Коды
возврата не печатаются автоматически, но их  можно  получить
как значение специального параметра shell $?.

     9.3.4.1.   Проверка кодов завершения

     После выполнения в  интерактивном  режиме  команды,  вы
можете увидеть код завершения при вводе:
        echo $?
     Рассмотрим следующий пример:
        $ cat hi
        This is file hi.
        $ echo $?
        0
        $ cat hello
        cat: cannot open hello
        $ echo $?
        2
        $
     В первом случае файл hi существует в вашем  справочнике
и вы имеете разрешение на чтение. С помощью команды  cat  вы
можете распечатать содержимое файла. Результат команды  cat:
код возврата 0, который вы получите, задав параметр  $?.  Во
втором случае файл либо не существует,  либо  вы  не  имеете
право  на  чтение.  Команда  cat  печатает   диагностическое
сообщение и возвращает код 2.
     shell программа нормально завершается, когда выполнится
последняя команда в файле.  Однако  вы  можете  использовать
команду exit для завершения программы. Более важно  то,  что
вы можете использовать  команду  exit  для  получения  кодов
возврата shell программы.

     9.3.5.   Циклы

     Операторы цикла for и while позволяют выполнить команду
или последовательность команд несколько раз.


     9.3.5.1.   Оператор for

     Оператор for выполняет  последовательность  команд  для
каждого элемента списка. Он имеет формат:
        for variable
            in a_list_of_values
        do
            command_1
            command_2
                 .
                 .
                 .
            last command
        done
     Для каждой  итерации  цикла  следующий  элемент  списка
присваивается переменной, данной в операторе for. Ссылка  на
эту переменную может быть сделана в любом месте  в  командах
внутри  оператора  do.  При  конструировании  каждой  секции


                            154
команд   вам   необходимо   убедиться,   что   каждому    do
соответствует done в конце цикла.
     Переменная может иметь любое имя. Например,  если  ваша
переменная названа var, то ссылка в списке  команд  на  $var
сделает значение доступным.  Если  оператор  in  опущен,  то
значением для var будет набор аргументов, заданный в команде
и доступный в специальном параметре $*. Список команд  между
ключевым  словом  do  и  done  будет  выполнен  для  каждого
значения.
     Когда команды будут выполнены для  последнего  элемента
списка, программа будет выполнять строку ниже done.

     9.3.5.2.   Оператор while

     Оператор цикла while использует  2  группы  команд.  Он
будет выполнять последовательность команд во  второй  группе
(список do ... done) до тех пор  пока  последняя  команда  в
первой группе (список while) возвращает состояние  "истина",
означающее, что выражение после do может быть выполнено.
     Общий формат оператора цикла while:
        while
            command_1
                .
                .
                .
            last command
        do
            command_1
                .
                .
                .
            last command
        done
     Например, программа enter.name  использует  цикл  while
для ввода списка имен в файл. Программа состоит из следующих
командных строк:
        $ cat enter.name
        while
           read x
        do
           echo $x>>xfile
        done
        $
     Внеся   некоторые   добавления,    получим    следующую
программу:
     $ cat enter.name
     echo Please type in each person's name and than a 
     echo Please end the list of names with a <^d>
     while read x
     do
        echo $x>>xfile
     done
     echo xfile contains the following names:
     cat xfile
     $
     Обратите внимание, что после завершения цикла программа
выполняет команды ниже done.
     В первых двух командах  echo  используются  специальные
символы, так что вы  должны  воспользоваться  кавычками  для


                            155
отмены специального значения. На следующем экране  приведены
результаты выполнения программы enter.name:
     $ enter.name
     Please type in each person's name and than a 
     Please end the list of names with a <^d>
     Mary Lou
     Janice
     <^d>
     xfile contains the following names:
     Mary Lou
     Janice
     $

     После того, как цикл завершится, программа  распечатает
все имена, содержащиеся в xfile.

     9.3.6.   Использование /dev/null

     Файловая система имеет файл /dev/null,  где  вы  можете
хранить нежелательный вывод. Например,  если  просто  ввести
команду who, то система ответит,  кто  работает  в  системе.
Если вы перенаправите вывод этой команды в /dev/null:
        who > /dev/null
то не получите ответа.

     9.3.7.   Условные операторы

                    Оператор if ... then
     Команда if говорит shell программе, что нужно выполнить
последовательность команд после then, если последняя команда
в  списке  команд  конструкции   if   выполнилась   успешно.
Конструкции if заканчиваются ключевым словом fi.
     Общий формат конструкции if:
        if
            command_1
                .
                .
                .
            last command
        then
            command_1
                .
                .
                .
            last command
        fi
     Например,   shell   программа   search    демонстрирует
применение  конструкции  if  ...  then.   Программа   search
использует команду grep для поиска слова в файле. Если  grep
выполнилась  успешно,  то  программа  отображает   найденное
слово. Экран будет выглядеть следующим образом:
        $ cat search
        echo Type in the word and the file name.
        read word file
        if grep $word $file
            then echo $word is in $file
        fi
        $


                            156
     Эта программа отображает вывод команды  grep.  Если  вы
хотите сохранить ответ  системы  на  команду  grep  в  вашей
программе,  то  воспользуйтесь  файлом  /dev/null,   изменив
командную строку if на следующую:
        if grep $word $file > /dev/null
     Теперь выполните команду  search.  Она  ответит  только
сообщением, указанным после команды echo.
     Конструкция  if  ...  then  ...  else  может  исполнять
альтернативный набор команд, стоящий после else,  в  случае,
если  последовательность  if  является  ложью.  Формат  этой
конструкции следующий:
        if
            command_1
                .
                .
                .
            last command
           .linthen
               command_1
                 .
                 .
                 .
               last command
           else
               command_1
                 .
                 .
                 .
               last command
        fi
     С помощью этой конструкции вы можете  усовершенствовать
программу search, так что она будет сообщать вам и найденное
слово и то, что слово не найдено. В  этом  случае  программа
search будет выглядеть следующим образом:
        $ cat search
        echo Type in the word and the file name.
        read word file
        if
            grep $word $file > /dev/null
        then
            echo $word is in $file
        else
            echo $word is NOT in $file
        fi
        $
                        Команда test
     Команда test используется для  организации  цикла.  Она
проверяет на истинность определенные условия и  полезна  для
организации условных конструкций. Если условие  истинно,  то
цикл будет продолжен. Если условие ложно, то цикл завершится
и будет выполняться  следующая  команда.  Некоторые  примеры
использования команды test:
       test -r file       истина, если файл существует
                              и доступен для чтения;
       test -w file       истина, если файл существует
                              и доступен для записи;
       test -x file       истина, если файл существует
                              и является выполняемым;
       test -s file       истина, если файл существует
                              и имеет как минимум один


                            157
                              символ;
       test var1 -eq var2 истина, если var1 равно var2;
       test var1 -ne var2 истина, если var1 не равно
                              var2.
     Пример. Создадим shell  программу,  которая  перемещает
все  исполняемые  файлы  из  текущего  справочника   в   ваш
справочник bin. Для этого воспользуемся командой test -x для
выбора исполняемых файлов. Программа mv.file будет выглядеть
следующим образом:
        $ cat mv.file
        echo type in the directory path
        read path
        for file
        do
          if test -x $file
             then
                mv $file $path/$file
          fi
        done
        $
     Конструкция case ... esac позволяет выбрать вам один из
несколько шаблонов и затем выполнить список команд для этого
шаблона.  Выражение-шаблон  должно  начинаться  с  ключевого
слова in, а правая круглая скобка должна быть помещена после
последнего  символа  каждого   шаблона.   Последовательность
команд для каждого шаблона заканчивается двумя  знаками  ;;.
Конструкция case должна быть закончена ключевым словом esac.
     Общий формат конструкции case:
        case word
        in
            pattern1)
               command line 1
                     .
                     .
                     .
               last command line
            ;;
            pattern2)
               command line 1
                     .
                     .
               last command line
            ;;
            pattern3)
               command line 1
                     .
                     .
               last command line
            ;;
            *)
               command line 1
                     .
                     .
               last command line
            ;;
        esac
     Конструкция case пытается найти word с шаблоном pattern


                            158
в первой секции шаблонов. Если поиск  удачен,  то  программа
выполняет  командные  строки  после   первого   шаблона   до
соответствующих знаков ;;.
     Если первый шаблон не найден, то осуществляется переход
ко второму шаблону. Если любой шаблон найден,  то  программа
не рассматривает остальные шаблоны, а переходит  к  команде,
следующей за esac. Знак * используется как шаблон для поиска
любого word и таким образом дает вам набор  команд,  который
будет выполнен, если никакой другой шаблон не будет  найден.
Поэтому  шаблон  звездочка  (*)  размещается  как  последний
шаблон  в  конструкции  case,  чтобы  другие  шаблоны   были
проверены первыми. Это поможет вам обнаружить некорректный и
неожиданный ввод.
     В шаблонах могут использоваться метасимволы *,  ?,  [].
Это обеспечивает гибкость программ.
     Рассмотрим  пример.  Программа  set.term  устанавливает
переменную TERM в соответствии с типом терминала, который вы
используете. Применяется следующая командная строка:
        TERM=terminal_name
     Шаблон * стоит последним в списке шаблонов.  Он  выдает
предупреждающее сообщение, что для указанного типа терминала
нет  соответствующего  шаблона  и  позволяет  вам  завершить
конструкцию case.
    Пример.
        $ cat set.term
        echo If you have a TTY 4420 type in 4420
        echo If you have a TTY 5410 type in 5410
        echo If you have a TTY 5420 type in 5420
        read term
        case term
                in
                    4420)
                         TERM-T4
                    ;;
                    5410)
                         TERM-T5
                    ;;
                    5420)
                         TERM-T7
                    ;;
                    *)
                    echo not a correcr terminal type
                    ;;
        esac
        export TERM
        echo end of programm
        $

     9.3.8.   Безусловная передача управления

     Команда  break  безусловно   останавливает   выполнение
любого цикла, в котором он встречается и передает управление
команде, следующей после ключевых слов done, fi или esac.
     В  предыдущем  примере  программы  set.term  вы  можете
использовать команду break,  вместо  echo,  чтобы  выйти  из
программы, как приведено в следующем примере:
    Пример.
        $ cat set.term
        echo If you have a TTY 4420 type in 4420


                            159
        echo If you have a TTY 5410 type in 5410
        echo If you have a TTY 5420 type in 5420
        read term
        case term
                in
                    4420)
                         TERM-T4
                    ;;
                    5410)
                         TERM-T5
                    ;;
                    5420)
                         TERM-T7
                    ;;
                    *)
                    break
                    ;;
        esac
        export TERM
        echo end of programm
        $
     Команда  continue  приведет  к  тому,   что   программа
немедленно перейдет к следующей итерации цикла while или for
без выполнения остальных команд в цикле.

     9.4.   Отладка программы

     Для  нахождения  и  корректировки  ошибок   вам   могут
понадобиться две опции команды sh:
     sh -v shellprogramname
           печатает вводимые shell строки, как если бы они
           были прочитаны системой;
     sh -x shellprogramname
           печатает команды и их аргументы по мере их
           выполнения.
     Для примера создадим shell программу, которая  содержит
ошибку:
        $ cat bug
        today=`date`
        echo enter person
        read person
        mail $1
        $person
        When you log off once into my office olease.
        $today
        MLH
        $
     Обратите внимание, что today равно выводу команды date,
которая заключена между знаками слабого ударения.
     При   выполнении   программы   bug,   чтобы   завершить
программу, вы должны нажать клавишу BREAK или DELETE.
     Чтобы отладить эту программу, попытайтесь выполнить  ее
с использованием sh -v. Будут напечатаны строки  файла,  как
если бы они были прочитаны системой:
        $ sh -v  bug tom
        today=`date`
        echo enter person
        enter person
        read person


                            160
        tom
        mail $1
     Обратите внимание, что  вывод  остановился  на  команде
mail, т.к. здесь обнаружена ошибка. Вы  должны  использовать
here document, чтобы перенаправить ввод в mail.
     Откорректированная  программа   bug   будет   выглядеть
следующим образом:
        $ cat bug
        today=`date`
        echo enter person
        read person
        mail $1 <
где  saverfile - это файл, который сохраняет вывод команды
                 для анализа.
     Предположим, вы хотите проверить вывод команды  grep  в
следующей командной строке:
        who | grep $1 | cut -c1-9
     Вы   можете   воспользоваться   командой   tee,   чтобы
скопировать вывод команды grep  в  файл  check  не  разрушая
остальной конвейер:
        who | grep $1 | tee check | cut -c1-9
     Файл check содержит копию вывода grep, как показано  на
следующем экране:
        $ who | grep mike | tee check | cut -c1-9
        mike
        $ cat check
        mike   tty61  Apr 10  10:30
        $

     9.4.1.   Модификация окружения

     Система UNIX позволяет вам модифицировать конфигурацию,
определяемую при вашей регистрации.
     Когда  вы  регистрируетесь  в  системе,  shell  вначале
проверяет файл .profile в вашем регистрационном справочнике.
Этот  файл  содержит  команды,   которые   управляют   вашей
конфигурацией. Этот файл может быть изменен в соответствии с
вашими потребностями. Чтобы проверить, существует ли в вашем
собственном справочнике файл .profile, введите:
        ls -al $HOME
     При  редактировании   файла   .profile   будьте   очень
внимательны. Прежде чем  выполнить  какие-либо  изменения  в
файле .profile сделайте копию этого файла, например с именем
safe.profile. Введите:
        cp .profile safe.profile


                            161
     9.4.2.   Добавление команд в файл .profile

     Отредактируем файл и  добавим  следующую  команду  echo
последней строкой в файл:
        echo Good Morning! I am ready to work for you.
     Если вы сделали какие-либо изменения в файле .profile и
хотите использовать его  в  текущей  сессии,  то  вы  можете
выполнить команды непосредственно с  использованием  команды
shell точка (.). shell вновь проинициализирует конфигурацию,
прочитав выполненные команды в файле  .profile.  Попытайтесь
сделать это, введите:
        . .profile
     Система ответит:
         Good Morning! I am ready to work for you.
         $

     9.4.3.   Установка характеристик терминала

     Команда stty  может  сделать  вашу  конфигурацию  более
удобной. Вы можете воспользоваться этой командой  с  опциями
-tabs и echoe.
stty -tabs - эта  опция  сохраняет  символы  табуляции   при
     печати. Она устанавливает табуляцию  более,  чем  на  8
     пробелов  (это  значение  установлено  по   умолчанию).
     Количество пробелов для  каждой  табуляции  может  быть
     разным;
stty echoe - эта опция стирает символы с  экрана  аналогично
     тому, как это делаете с помощью BACKSPACE.
     Вы можете включить эти команды stty  в  файл  .profile.
Если вы воспользуетесь  командой  tail,  которая  отображает
несколько  последних  строк  файла,  то  вы  можете  увидеть
результат  добавления  этих  трех  командных  строк  в  файл
.profile:
        $ tail -3 .profile
        echo Good Morning! I am ready to work for you.
        stty -tabs
        stty echoe
        $

     9.5.   Использование shell переменных

     Несколько    переменных,    зарезервированных    shell,
используются в файле .profile.
     Рассмотрим 4 основные переменные:
HOME - эта переменная дает имя пути вашего  регистрационного
     справочника. С помощью команды cd перейдите  в  него  и
     введите:
        pwd
     Теперь введите:
        echo $HOME
$HOME - это аргумент, используемый командой cd. Если  вы  не
     указывали справочник, то cd переместит вас в $HOME;
PATH - эта переменная дает путь  поиска  для  обнаружения  и
     выполнения команд. Чтобы  посмотреть  текущее  значение
     переменной PATH, введите:
        echo $PATH
Система распечатает текущее значение PATH:
        $ echo $PATH


                            162
        :/mylogin/bin:/bin:/usr/bin
        $
     Двоеточие (:) является разделителем между именами путей
в  строке,  присваиваемой  переменной  $PATH.   Если   перед
двоеточием ничего не  указано,  то  подразумевается  текущий
справочник.
     Если вы хотите установить  специальный  справочник  для
shell  программ  с  именем   :/project/bin,   добавьте   его
следующим образом:
        PATH="$PATH:/project/bin"
TERM - эта переменная сообщает shell  тип  терминала.  Чтобы
     присвоить этой переменной значение, вы должны выполнить
     3 команды в следующем порядке:
        TERM=terminal_name
        export TERM
        tput init
     Первые две строки  совместно  сообщают  компьютеру  тип
терминала, который вы используете. Последняя строка сообщает
терминалу, что компьютер находится в состоянии ожидания  для
связи с терминалом, тип которого указан в переменной TERM.
     Если  вы  хотите,   чтобы   эти   команды   выполнялись
автоматически при каждой вашей регистрации, то включите их в
файл .profile;
PS1 - эта переменная устанавливает первичную подсказку shell
     (по  умолчанию  это  знак  $).  Изменить  подсказку  вы
     можете,  изменив  значение  переменной  PS1   в   файле
     .profile.