else ... if ... then ... else if ... ... fi fi fi можно использовать сокращенную запись: if ... then ... elif ... then ... elif ... ... fi Конструкция if команда1 then команда2 fi может быть записана в виде: команда1 && команда2 В конструкции команда1 || команда2 команда2 выполняется только в том случае, если команда1 не - 23 - была выполнена успешно. Кодом завершения обеих конструкций является код завершения последней простой команды. 3.8. Локальный файл В процедуре tel, рассмотренной в ранее, исходные данные для команды grep берутся из файла /usr/lib/pfone. Обрабаты- ваемые данные могут непосредственно включаться в командный файл. Для этого они оформляются в виде локального файла. В следующем примере: for i do grep $i <&lt;<&lt;! ... Иванов И.И. 224 01 01 Петров П.П. 123 07 07 Сизов В.И. 224 44 94 ... ! done строки, заключенные между символами <&lt;<&lt;! и !, передаются команде grep в качестве данных стандартного файла ввода. Строка-ограничитель ! выбрана здесь произвольно: главное, чтобы она совпадала с последовательностью символов, стоящей за знаками <&lt;<&lt;. Если следующая за <&lt;<&lt; последовательность символов не начинается со знака \, то прежде чем локальный файл станет доступным командe, в нем выполняются все подстановки пара- метров. Например, пусть файл edg содержит строки вида: ed $3 <&lt;<&lt; % g/$1/s//$2/g w % при вызове: edg строка1 строка2 file будет достигнут результат, который можно получить при выпол- нении следующей последовательности команд: ed file <&lt;<&lt; % g/строка1/s//строка2/g w % - 24 - 3.9. Отладка командных файлов В SHELL используются два механизма отладки командных файлов. Первый из них: set -v выводит строки командного файла по мере их чтения. Этот режим применяется при поиске синтаксических ошибок. Для его использования не требуется производить модификацию команд- ного файла, например: sh -v proc... здесь proc - имя командного файла. Ключ -v может использо- ваться вместе с ключом -n, предотвращающим выполнение следу- ющих за ним команд (команда set -n блокирует терминал до тех пор, пока не вводится признак конца файла EOF). Команда set -х выводит команды по мере их выполнения. Для отмены ключей -x и -v можно воспользоваться командой set - а для установки - присвоить соответствующее значение макро- переменной -. 4. ПАРАМЕТРЫ И ОБЛАСТЬ ДЕЙСТВИЯ МАКРОПЕРЕМЕННЫХ Макропеременные, определенные в одном процессе, при отсутствии явных указаний не доступны в других процессах. Для того чтобы обеспечить возможность передачи порождаемому процессу какой-либо информации, в языке предусмотренны средства, которые позволяют: - передавать команде параметры; - экспортировать определения макропеременных из среды текущего процесса в среду порождаемого; - определять макропеременные и передавать их определения в среду порождаемого процесса без изменения среды теку- щего. Так, в следующем примере: USER=nata команда перед выполнением файла команда макропеременная USER - 25 - принимает значение nata. При использовании флага -k опера- торы вида имя=значение могут вставляться в любое место списка параметров. Такие имена называются ключевыми пара- метрами. Значения параметров присваиваются макропеременным с именами "1", "2", ... N (поскольку число в имени макропе- ременной указывает позицию параметра в командной строке, такие параметры называются позиционными). Для того чтобы присвоить значения позиционным парамет- рам непосредственно из командного файла используется команда set. Так, в следующем примере set * параметру "1" будет присвоено значение имени первого файла текущего справочника, параметру "2" - имя второго файла и т.д. При выполнении команд интерпретатор производит следую- щие действия: - Подстановка значений параметров, например: $user - Подстановка результатов выполнения команд, например: `pwd` В тех случаях, когда в строке требуется выполнить нес- колько вложенных макроподстановок, используется встро- енная команда eval. Например, если значением макропере- менной X является строка $y, а макропеременной y - pqr, то команда eval echo $X выдаст строку pqr. Результаты выполнения команды eval являются входными данными для SHELL, который считывает их и выполняет в качестве команд. Таким образом, конструкция wg='eval who | grep' $wg fred эквивалентна команде who | grep fred - 26 - В этом примере без команды eval не обойтись, так как метасимвол | при последующей макроподстановке не интерпретируется. - Интерпретация символов-разделителей. Символы, полученные в результате выполнения указанных выше подстановок, разбиваются затем на слова, не содер- жащие разделителей. Пробелами здесь названы символы, являющиеся разделителями слов. Список этих символов содержится в макропеременной IFS; по умолчанию к ним относятся пробел, символы горизонтальной табуляции и новой строки. Если специальное значение пробела отме- нить одним из существующих способов, то он будет интерпретироваться соответствующей последовательностью символов. Например, командa echo '' будет выдавать пустую строку, поскольку она является первым аргументом команды echo, в то время как вызов команды echo $null будет осуществляться без аргументов, если значение мак- ропеременной null не определено или определено как пустая строка. - Задание имен файлов. На этом этапе в словах осуществляется поиск символов *, ? и [...] (являющихся образцами имен файлов) и замена каждого слова списком имен файлов, расположенных в алфавитном порядке. Каждое имя файла рассматривается как отдельный параметр. Над словами, содержащимися в операторе цикла for, выполняются все перечисленные действия. В опрераторе case выполняется только подстановка значения параметра, указывае- мого после ключевого слова case. Как отмечалось, в языке SHELL существуют три механизма экранирования метасимволов (с использованием символов \, '...' и "..."). Внутри строк, заключенных в двойные кавычки, выполняются только подстановки значений параметров и резуль- татов выполнения команд. Далее перечислены символы, которые при заключении их в двойные кавычки не теряют своего специ- ального значения: - 27 - $ подстановка значений параметров; ` подстановка результатов выполнения команд; ограничитель экранируемой строки; \ экранирует метасимволы $, `, " и \. Например, в команде echo $х значение макропеременной x является единственным аргументом. Аналогично, в команде echo $* все позиционные параметры рассматриваются в качестве единст- венного аргумента; эта команда эквивалентна следующей: echo $1 $2 ... Макровызовы $@ и $* идентичны, за исключением способов их экранирования. Команды echo $@ и echo $1 $2 ... эквивалентны. В результате их выполнения будут выдаваться значения всех позиционных параметров. На рисунке 1 показано воздействие механизмов экраниро- вания на каждый из метасимволов языка SHELL. Метасимволы $ * ` " ' -|------------------| ' | - - - - - t | ` | + - - t - - | " | + + - + t - | _|__________________| + метасимвол экранируется; - метасимвол не экранируется; t ограничитель экранируемой строки. Рис.1 - 28 - 4.1. Передача параметров Как позиционные, так и ключевые параметры могут быть получены в процессе вызова командного файла. Ключевые пара- метры, кроме того, можно сделать доступными еще одним спосо- бом: нужно явно указать, что они вводятся в среду процесса (становятся макропеременными). Например, команда: export USER BOX указывает на то, что такими макропеременными являются USER и BOX. При вызове командного файла создаются копии всех мак- ропеременных. Изменение значений макропеременных не вызывает их модификации в порождающем процессе. Командный файл не может изменить состояние порождающего процесса без явного вызова со стороны порождающего процесса. (Исключение сос- тавляют дескрипторы распределенных файлов). Имена макропеременных, имеющих постоянные значения, могут задаваться с помощью команды readonly (только для чте- ния). Формат этой команды совпадает с форматом команды export: readonly имя... После выполнения этой команды значения перечисленных макро- переменных больше изменить нельзя. 4.2. Подстановка значений параметров Если параметру языка SHELL не было присвоено значение, то он определяется как пустая строка. При выполнении команды echo ${d-.} выдается значение макропеременной d, если она определена, или символ '.' - в противном случае. В команде echo исполь- зуются обычные соглашения об отмене специальных значений метасимволов. Следовательно, если значение макропеременной d не было определено, то команда echo ${d-'*'} выведет символ *. Аналогично, команда echo ${d-$X} если макропеременная d определена, выдаст ее значение, если нет - значение макропеременной X. Значение по умолчанию макропеременной может быть опре- делено следующим образом: - 29 - echo ${d=.} если макропеременная d не определена, ей присваивается сим- вол '.' (для позиционных параметров обозначение ${...=...} использовать нельзя). Команда echo ${d?сообщение} выдает значение макропеременной d, если оно определено, и сообщение - если не определено. В последнем случае выполне- ние командного файла завершается. Если сообщение отсутст- вует, то выдается стандартная диагностика интерпретатора. Командный файл, часть параметров которого должна иметь опре- деленные значения, может начинаться следующим образом: : ${USER?} ${HOME?} ${BIN?} ... Двоеточие : представляет собой встроенную команду языка SHELL, предназначенную для оценки значений своих параметров. Если значение хотя бы одной из переменных USER, HOME или BIN не определено, выдается диагностика и выполнение командного файла прекращается. 4.3. Подстановка результатов выполнения команд В языке SHELL существует возможность использования результата выполнения команд в различных целях. Так, стан- дартным выходом команды pwd является имя текущего справоч- ника, и если таким справочником является, например, /usr/nata/bin, то команда d=`pwd` будет эквивалентна команде d=/usr/nata/bin Строка, заключенная между обратными кавычками `...`, воспри- нимается как команда и заменяется результатом выполнения этой команды. Команды записываются с использованием обычных соглашений об отмене специальных значений метасимволов, за исключением того, что специальное значение символа обратной кавычки "`" отменяется символом \. Например, команда ls `echo $1` эквивалентна команде ls $1 - 30 - Везде, где разрешена подстановка значений параметров, может производиться и подстановка результатов выполнения команд (в том числе и в локальных файлах). Обработка резуль- татов в обоих случаях выполняется одинаково. Это позволяет использовать в процедурах языка SHELL команды, предназначен- ные для обработки строк. Примером такой команды является команда basename, которая удаляет из слова указанный суф- фикс. Например, в результате выполнения команды basename main.c .c будет получена последовательность символов main. Использова- ние команды basename можно проиллюстрировать следующим фраг- ментом команды cc: case $A in ... *.c) B=`basename $A .c` ... esac В этом примере макропеременной B присваивается значение мак- ропеременной A, из которой удален суффикс .c. 4.4. Обработка ошибок Действия интерпретатора при обнаружении ошибки зависят от двух обстоятельств: типа ошибки и режима работы интерпре- татора. Режим работы интерпретатора считается интерактивным в том случае, если ввод/вывод информации осуществляется с терминала или интерпретатор вызван с ключом -i. Приведем список причин, которые приводят к ошибкам при выполнении команды: - неверное указание файлов ввода/вывода (например, файл не существует или не может быть создан); - самой команды не существует, или она не может быть выполнена; - команда вызвалась нормально, но ее код завершения имеет ненулевое значение. Если интерпретатор работает в интерактивном режиме, то, независимо от результата завершения предыдущей команды, он переходит к выполнению следующей. В не интерактивном режиме два вида ошибок приводят к прекращению обработки командного файла: - синтаксическая ошибка в операторах управления (while, until, if, for); - 31 - - ошибка при выполнении встроенной команды. Для того чтобы обеспечить прекращение выполнения команды при обнаружении любой из указанных ошибок, при вызове интерпретатора необходимо использовать ключ -e. 4.5. Обработка прерываний Сигналы, вызывающие прерывание выполнения команды, перечислены в табл.1. В зависимости от своего режима работы, при получении сигнала интерпретатор поступает следующим образом. Если режим работы - интерактивный, то (также как и при обнаруже- нии ошибки) завершив выполнение текущей команды, он перейдет к выполнению следующей. Если же режим - неинтерактивный, интерпретатор завершит выполнение текущей команды, после чего либо прекратит работу, либо возвратится в интерактивный режим. Таблица 1 Сигналы системы ДЕМОС ------------------------------------------------------------ Сигнал Описание ------------------------------------------------------------ 0 выход из интерпретатора (по любой причине, включая достижение конца файла) 1 зависание 2 прерывание 3* выход (CTRL/Q создается файл core, содержащий копию оперативной памяти процесса) 4* запрещенная команда (не сбрасывается после приема) 5* использование команды BPT (прерывание трассировки) 6* использование команды прерывания ввода/вывода IOT 7* использование команды EMT 8* ошибка операции с плавающей точкой 9 уничтожить процесс (не может быть перехвачен или про- игнорирован) 10* ошибка шины 11* нарушение защиты памяти 12* неправильный параметр в системном вызове 13 запись по каналу межпроцессной связи при отсутствии чтения процессом-получателем 14 прерывание по заданному времени 15 прерывание программы (по команде kill) 16 не используется ------------------------------------------------------------ Команды, отмеченные знаком *, осуществляют копирование оперативной памяти процесса. Однако, сам интерпретатор игно- рирует эти сигналы. - 32 - При поступлении сигнала прерывания выполняются некото- рые стандартные действия, после чего обрабока командного файла обычно завершается. Если это по тем или иным причинам не устраивает пользователя, он может задать свои методы реакции на определенные типы прерываний. Для этой цели в языке SHELL применяется встроенная команда trap. Например, команда trap 'rm /tmp/ps$$; exit' 2 перехватывает сигнал 2 (прерывание) и выполняет команду rm /tmp/ps$$; exit Встроенная команда exit прерывает выполнение командного файла. Существует три способа обработки сигналов: 1. Сигналы игнорируются (в этом случае сигнал вообще не посылается процессу). 2. Сигналы перехватываются (реакция на сигнал обеспечивается самим процессом). 3. Сигналы пропускаются без обработки. Работа процесса завершается. Если при входе в командный файл сигнал игнорируется, то игнорируется и команда trap. Если аргументом команды trap является пустая строка, то процедура игнорирует сигналы. В качестве примера можно при- вести фрагмент команды nohup: trap '' 1 2 3 15 после выполнения которого как процедура, так и вызывающие ее команды будут игнорировать перечисленные сигналы. Стандартная реакция на сигналы может быть восстанов- лена, например, следующей командой: trap 2 3 Список текущих значений сигналов системы может быть получен с помощью команды trap Еще одним примером использования команды trap (без пос- ледующего выхода из командного файла) является процедура - 33 - scan, которая осуществляет просмотр подсправочников в теку- щем справочнике и выполнение команд, вводимых с терминала, до получения сигнала конец_файла или прерывание. Сигнал прерывание действует только по окончании выполнения команды. Текст процедуры scan имеет следующий вид: d=`pwd` for i in * do if test -d $d/$i then cd $d/$i while echo $i: trap exit 2 read x do trap : 2; eval $x; done fi done Встроенная команда read x считывает строки из файла стан- дартного ввода и присваивает результат их выполнения макро- переменной x. Сигналы конец_файла или прерывание прекращают выполнение этой команды с кодом завершения, не равным нулю. 5. ВЫЗОВ ИНТЕРПРЕТАТОРА Вслед за регистрацией пользователя в системе (с помощью команды login) вызывается интерпретатор языка SHELL. Если регистрационный справочник пользователя содержит файл .pro- file, то прежде чем с терминала будет принята хотя бы одна команда, интерпретатор выполняет этот файл (подразумевается, что файл .profile содержит команды). При вызове могут указываться следующие ключи: -c строка Команды считываются из заданной строки. -s Команды читаются из стандартного файла ввода. Сообще- ния интерпретатора записываются в стандартный файл диагностик. -i Интерактивный режим работы. Если первым символом параметра "0" является знак -, то команды считываются из файла .profile. 6. СВОДКА ОСНОВНЫХ КОНСТРУКЦИЙ ЯЗЫКА SHELL - 34 - Таблица 2 СПЕЦИАЛЬНЫЕ СИМВОЛЫ ------------------------------------------------------------ Символ Описание ------------------------------------------------------------ # коментарий; | создать канал связи процессов; ~ создать канал связи процессов; ; разделитель команд; & запустить следующий процесс, не ожидая окончания пре- дыдущего; && выполнить следующую команду, если код завершения пре- дыдущей равен нулю; || выполнить следующую команду, если код завершения пре- дыдущей не равен нулю; '...' литеральная константа; "..." после подстановки значений макропеременных, строка рассматривается как литеральная константа; \ отменяет специальное значение следующего за ним сим- вола. ------------------------------------------------------------ Таблица 3 ВВОД-ВЫВОД ------------------------------------------------------------ Конструкция Описание ------------------------------------------------------------ [d]<&lt; следующий параметр является именем файла, кото- рый используется в качестве стандартного файла ввода с дескриптором d (по умолчанию d=0); [d]>&gt; следующий параметр является именем файла, кото- рый используется в качестве стандартного файла вывода с дескриптором d (по умолчанию d=1); [d]>&gt;>&gt; то же что >&gt;, за исключением того, что выводимая информация дописывается к концу содержимого файла; [d]<&lt;<&lt; ввод осуществляется до тех пор, пока не встре- чается последовательность символов, стоящая за данной конструкцией; [d]<&lt;&цифра в качестве стандартный файла ввода используется файл с дескриптором цифра; [d]>&gt;&цифра в качестве файла стандартного вывода использу- ется файл с дескриптором цифра; [d]<&lt;&- закрыть стандартный файл ввода; [d]<&lt;>&gt; открыть указанный файл для чтения (записи). ------------------------------------------------------------ - 35 - Таблица 4 ЗАДАНИЕ ИМЕН ФАЙЛОВ ------------------------------------------------------------ Конструкция Описание ------------------------------------------------------------ ? соответствует одиночному символу; * соответствует строке символов (в т.ч. пустой); [...] соответствует одному из перечисленных символов; пара символов, разделенная знаком -, соответст- вует любому символу из указанного промежутка; ------------------------------------------------------------ Таблица 5 ПОДСТАНОВКА ЗНАЧЕНИЙ ПАРАМЕТРОВ ------------------------------------------------------------ Конструкция Описание ------------------------------------------------------------ $n заменить $n значением n; $* "1 2 ..." $@ "1" "2" ... $# число позиционных параметров; $- ключи, которые вводятся при вызове или с помощью команды set; $? код завершения последней команды; $$ номер текущего процесса; $! номер процесса последней фоновой команды; имя=значение определение макропеременной; ${имя-слово} если имя определено, подставить значение, иначе - слово; ${имя=слово} использовать значение имени; если не опреде- лено - присвоить и использовать значение слово; ${имя?слово} использовать значение имени, если определено, иначе - напечатать слово и прекратить выполне- ние командного файла; ${имя+слово} использовать слово, если имя определено, иначе - ничего не делать; $HOME имя справочника для команды cd без параметров; $PATH список имен справочников для поиска команд; $MAIL файл для приема почты; $PS1 подсказка интерпретатора (по умолчанию $); $PS2 подсказка интерпретатора для продолжении ввода команды (по умолчанию >&gt;); $IFS разделители слов командной строки (по умолча- нию пробел, знак табуляции и новой строки); ------------------------------------------------------------ - 36 - Продолжение таблицы 5 ------------------------------------------------------------ Конструкция Описание ------------------------------------------------------------ $TERM тип терминала. ------------------------------------------------------------ - 37 - КОМАНДНЫЙ ЯЗЫК for имя [in слово...] do список_команд done case слово in [обр1 [|обр2]...) список_команд;;] ... esac if список_команд then список_команд [elif список_команд then список_команд] [else список_команд] fi while список_команд [do список_команд] done until список_команд [do список_команд] done (список_команд) { список_команд; } break [n] выход из циклов for, case, while или until на уровне n; continue переход к следующей итерации цикла for, while или until; exit [N] выход с кодом завершения N; : не производит никаких действий, за исключением подста- новки значений макропеременных. - 38 - ВСТРОЕННЫЕ КОМАНДЫ . файл выполнить командный файл в рамках текущего процесса; eval [команда ...] провести все макроподстановки и выполнить "команду ..."; exec [команда ...] текущий процесс заменить процессом выполнения команды ...; export [имя ...] копировать определение макропеременной имя в среду порождаемых процессов; read имя ... считать файл стандартного ввода и присвоить значение макропеременной имя; readonly [имя ...] запретить переопределение макропеременой; set [-ekntuvx [пар ...]] установить режимы работы интерпретатора (значения клю- чей см. в описании команды sh); shift переименовать позиционные параметры; 1=2 ...; times выдать время, затраченное на выполнение процесса; trap [команда] [n] выполнить команду, если получен сигнал n; umask [nnn] маска создания файла - обратный код (в восьмеричной системе); wait [pid] ожидать окончания процесса с номером pid. - 39 - СОДЕРЖАНИЕ АННОТАЦИЯ ......................................... 2 1. ВВЕДЕНИЕ .......................................... 3 2. ОСНОВНЫЕ ПОНЯТИЯ .................................. 3 2.1. Простые команды ................................. 4 2.2. Фоновые процессы ................................ 4 2.3. Задание имен файлов ............................. 4 2.4. Отмена специального значения метасимволов ....... 6 2.5. Задание файлов ввода/вывода ..................... 6 2.6. Связь процессов, конвейеры и фильтры ............ 8 2.7. Макропеременные ................................. 9 2.8. Выдача подсказок ................................ 12 2.9. Составные команды ............................... 12 2.10. Встроенные команды .............................. 12 3. КОМАНДНЫЕ ФАЙЛЫ ................................... 15 3.1. Комментарии ..................................... 17 3.2. Команда test .................................... 17 3.3. Оператор for .................................... 18 3.4. Оператор case ................................... 19 3.5. Операторы while и until ......................... 21 3.6. Операторы break и continue ...................... 22 3.7. Оператор if ..................................... 22 3.8. Локальный файл .................................. 24 3.9. Отладка командных файлов ........................ 25 4. ПАРАМЕТРЫ И ОБЛАСТЬ ДЕЙСТВИЯ МАКРОПЕРЕМЕННЫХ ...... 25 4.1. Передача параметров ............................. 29 4.2. Подстановка значений параметров ................. 29 4.3. Подстановка результатов выполнения команд ....... 30 4.4. Обработка ошибок ................................ 31 4.5. Обработка прерываний ............................ 32 5. ВЫЗОВ ИНТЕРПРЕТАТОРА .............................. 34 6. СВОДКА ОСНОВНЫХ КОНСТРУКЦИЙ ЯЗЫКА SHELL ........... 34 - 40 -