Командный язык shell Производственно-внедренческий кооператив "И Н Т Е Р Ф Е Й С" Диалоговая Единая Мобильная Операционная Система Демос/P 2.1 Командный язык SHELL Москва 1988 АННОТАЦИЯ Описывается интерпретатор командного языка shell. Опи- саны элементы языка, оператор И структура программ на shell, а также встроенные возможности. 1. ВВЕДЕНИЕ В семействе операционных систем, совместимых с ОС UNIX, язык SHELL используется в качестве стандартного языка управ- ления заданиями, т.е. является основным языком общения поль- зователя с системой. Он предоставляет средства для описания таких действий, как, например, запуск какого-либо компиля- тора или программы, создание, копирование и уничтожение фай- лов, опрос состояния процессов. Кроме того, SHELL широко применяется и в качестве языка разработки особых программ - командных файлов. Последнее свойство объясняется тем, что SHELL имеет много общего с универсальными языками программи- рования, в частности, конструкции, которые позволяют созда- вать программы, содержащие проверки условий и циклы. Важным достоинством языка, является возможность его поэтапного изучения. Для того чтобы начать работу в сис- теме, пользователю достаточно ознакомиться с разделом "Основные понятия" данного документа. 2. ОСНОВНЫЕ ПОНЯТИЯ После регистрации пользователя вся дальнейшая работа с системой выполняется под управлением программы sh - интерп- ретатора командного языка SHELL. Во время работы пользователь выдает команды и получает сообщения системы о результатах их выполнения. Как правило, при получении команды интерпретатор определяет имя файла, содержащего программу, которую необходимо выполнить, и порождает процесс, который работает под управлением заданной программы. Исключения составляют случаи, когда вызываются встроенные команды языка SHELL, при этом указанные действия выполняются непосредственно интерпретатором без порождения нового процесса. Поскольку, в качестве имени команды может указываться любой файл, содержащий исполняемую программу, существует практически безграничная возможность расширения набора команд. С понятием процесса в ДЕМОС связано понятие среды. Среда формируется процессом-родителем и содержит дополни- тельную информацию о способе выполнения процесса. Каждому процессу ставится в соответствие три файла: стандартный файл ввода, стандартный файл вывода и файл диагностических сооб- щений. При запуске команды пользователь может указать файлы которые будут применяться в качестве стандартных. По умол- чанию, ввод/вывод информации осуществляется с терминала пользователя. Характерной чертой систем, совместимых с ОС UNIX, явля- ется естественная возможность работы с несколькоми процес- сами одновременно. Пользователь может указать в команде, что соответствующий процесс должен работать как фоновый - 3 - (т.е. переход к приему следующей команды осуществляется без ожидания окончания данного процесса). Кроме того, сущест- вует возможность задания команд, для выполнения которых интерпретатор порождает несколько взаимодействующих процес- сов. При этом создается цепочка процессов (конвейер), в которой обрабатываемая информация передается от одного про- цесса другому по каналу межпроцессной связи. 2.1. Простые команды Простые команды состоят из одного или нескольких слов, разделенных пробелами. Первое слово является именем выполня- емой команды; все остальные слова передаются команде в качестве параметров. Например, who представляет собой команду, которая выдает информацию о пользователях, зарегистрированных в системе. Команда ls -l выдает список файлов текущего справочника. Параметр -l ука- зывает команде ls, что нужна информация о характеристиках, размере и дате создания каждого файла. 2.2. Фоновые процессы Для того, чтобы выполнить команду, интерпретатор языка SHELL обычно создает новый процесс и ждет его завершения. Пользователь может запускать процессы в фоновом режиме, при этом интерпретатор переходит к обработке следующей команды сразу после запуска процесса, не ожидая окончания ранее запущенного. Например, команда: cc program.c & вызывает компилятор для обработки файла program.c. Символ &, завершающий строку, указывает интерпретатору команд, что следует перейти к обработке следующей команды без ожидания окончания трансляции. Для последующего наблюдения за ходом процесса система сообщает уникальный номер, по которому можно запрашивать информацию о его состоянии. 2.3. Задание имен файлов В языке SHELL предусмотрен механизм для генерации списка имен файлов, которые соответствуют некоторому образцу. Например, при выполнении команды: ls -l *.c в качестве параметров ls передаются имена всех файлов - 4 - текущего справочника, которые оканчиваются на .c. Символ * имеет специальное значение (т.е. является метасимволом языка SHELL), ему соответствует любая строка (в том числе пустая). При задании образцов могут использоваться следующие метасим- волы: * соответствует любой строке символов (включая пустую строку); ? соответствует любому одиночному символу; [...] соответствует любому из перечисленных внутри скобок символов; пара символов, разделенных знаком минус, будет соответствовать любому символу из заданного лексического промежутка. Например, образцу [А-Я]* соответствуют все имена в текущем справочнике, которые начи- наются с прописной русской буквы, а образцу /usr/nata/test/? соответствуют все односимвольные имена из справочника /usr/nata/test. Если не найдено ни одного файла, соответст- вующего заданному образцу, то в качестве параметра команде передается сам образец. Описанный механизм сокращает время набора команд и позволяет выбирать имена, отвечающие нужному образцу. Он также может использоваться при поиске файлов. Например, команда echo /usr/nata/*/core находит и печатает полные имена всех файлов core из подспра- вочников справочника /usr/nata (команда echo является стан- дартной командой ДЕМОС, которая печатает свои параметры, разделяя их пробелами). Из общих правил, указанных для образцов, имеется единственное исключение. Символ '.' в начале имени файла должен указываться явно. Поэтому команда: echo * будет выдавать все имена файлов в текущем справочнике, кото- рые не начинаются с точки, а команда: echo .* - 5 - напечатает имена файлов, начинаюшиеся с точки. Это позво- ляет исключить неумышленную подмену имен "." и "..", которые соответственно означают текущий справочник и основной спра- вочник. 2.4. Отмена специального значения метасимволов Для языка SHELL символы имеют специальное значение (полный список метасимволов приведен в табл.2 Приложения). Любой метасимвол, которому предшествует обратная черта, теряет свое специальное значение (действие \ распространя- ется только на следующий за ним символ, при этом сам знак \ игнорируется). Так, команда: echo \? напечатает только знак вопроса '?', а команда: echo \\ выдаст лишь один символ \. Для записи длинных конструкций более чем в одной строке, специальное значение символа новой строки \n отменяется. Знак \ удобен для отмены специального значения отдель- ных символов. Когда же необходимо экранировать сразу нес- колько метасимволов, такой механизм оказывается слишком гро- моздким. В этом случае последовательность знаков заключается в апострофы. Например, команда: echo хх'****'хх напечатает хх****хх Символ новой строки \n, заключенный в апострофы, теряет свое специальное значение. Однако, экранировать сам апостроф таким способом нельзя. Еще одним механизмом отмены специального значения сим- волов является заключение их в двойные кавычки. 2.5. Задание файлов ввода/вывода Результаты работы большинства команд записываются в стандартный файл вывода. По умолчанию вся выдаваемая процес- сом информация отображается на терминал пользователя. При необходимости она может быть записана и в обычный файл. Так, в следующем примере: - 6 - ls -l > filels конструкция "> filels" рассматривается как указание исполь- зовать в качестве стандартного вывода команды ls заданный файл (в данном случае файл filels). Если файл с данным име- нем отсутствует, интерпретатор команд создает его. Если файл существует, то его исходное содержимое заменяется информа- цией, выдаваемой командой. Если требуется сохранить содержимое файла, добавив в него поступающую информацию, вместо символа >&gt; используется конструкция >&gt;>&gt;. Например: ls >&gt;>&gt; filels В данном случае, если файл не существует, он также предвари- тельно создается системой. Аналогичные возможности предоставляются и для переопре- деления стандартного файла ввода (по умолчанию данные вво- дятся с терминала). Для этой цели используется символ <&lt;. Например, команда: wc <&lt; filels выдает количество строк файла filels. Далее перечислены основные конструкции, используемые для задания файлов ввода/вывода. >&gt; файл В качестве стандартного файла вывода используется файл, который перезаписывается заново или создается, если ранее не существовал. >&gt;>&gt; файл Поступающая информация добавляется к содержимому файла. Если файл не существует, он предварительно создается. <&lt; файл В качестве стандартного файла ввода используется файл. <&lt;<&lt; файл Чтение локального файла (см. раздел 4.8). Последующие строки передаются команде в качестве информации стан- дартного файла ввода до тех пор, пока не встретится строка, содержащая последовательность символов файл. Если специальное значение первого символа строки файл отменено, выполняются подстановки значений макропере- менных и результатов выполнения команд. >&gt;& цифра Информация, записываемая в файл с дескриптором цифра, - 7 - передается в стандартный файл вывода. <&lt;& цифра Стандартным файлом ввода является файл с дескриптором цифра. <&lt;&- Файл стандартного ввода закрыт на запись. >&gt;&- Файл стандартного вывода закрыт на чтение. 2.6. Связь процессов, конвейеры и фильтры Информация, выдаваемая в стандартный файл вывода одной командой, может непосредственно передаваться другой команде в качестве содержимого стандартного файла ввода. Например, в результате работы команд: ls | wc будет выдано общее число символов в именах текущего справоч- ника. Составная команда, образованная с помощью операции "|", называется конвейером. В данном случае она выполняет действие эквивалентное командам: ls >&gt; filels wc <&lt; filels rm filels за тем исключением, что для хранения промежуточных результа- тов не используется никаких файлов. В конвейере каждая команда работает как параллельный независимый процесс, информация передается в одном направлении. Если входные дан- ные процесса-получателя еще не готовы, или выходные данные процесса-источника не успевают обрабатываться, то выполнение соответствующего процесса приостанавливается. Фильтром называется команда, которая, получая данные из стандартного файла ввода, производит какую-либо работу и выдает результат в стандартный файл вывода. Типичным приме- ром фильтра может служить команда grep, которая, читая дан- ные из стандартного файла ввода, выбирает строки, содержащие указанную последовательность символов и выдает их в стан- дартный файл вывода. Например, команда: ls | grep old выдает только те имена файлов текущего справочника, которые содержат последовательность символов old. Конвеер может состоять более чем из двух процессов. Например, конструк- ция: ls | grep bak | wc -l - 8 - может использоваться для подсчета числа имен файлов в теку- щем справочнике, которые содержат последовательность симво- лов bak. 2.7. Макропеременные Имя макропеременной представляет собой последователь- ность букв, цифр и символов подчеркивания, начинающуюся с буквы. При выполнении оператора присваивания в командную среду текущего процесса заносится запись типа имя=значение, в левой части которой стоит имя макропеременной, а в правой - последовательность символов, являющаяся ее значением. В командной строке все вхождения вида $имя заменяются значени- ями соответствующих макропеременных (исключение составляют случаи, когда подобные конструкции заключены в апострофы '...' или символу $ предшествует знак \). Примеры: USER=nata HOME=/usr/nata присваивание значений макропеременным USER и HOME; null= присваивание макропеременной значения пустой строки; echo $USER выполнение подстановки значения макропеременной (результат - строка nata). Переменные могут использоваться для введения сокраще- ний. Так, при выполнении команд: b=/usr/nata/bin mv pgm $b файл pgm будет перемещен из текущего справочника в справоч- ник /usr/nata/bin. В более общем виде макровызов записывается следующим образом: ${имя_макропеременной} Фигурные скобки в данном случае играют роль разделителей и используются тогда, когда за именем следует буква или цифра. Например, в результате выполнения группы команд: П=ПРОБ ПА=ПЕРА echo ${П}А $ПА - 9 - будет выдан текст: ПРОБА ПЕРА В языке SHELL существуют специальные макропеременные, которые определяются перед началом выполнения команды (иск- лючение составляет макропеременная ?, которая получает зна- чение после выполнения команды): ? Десятичное целое число - код завершения последней выполненной команды. В большинстве случаев, при успеш- ном выполнении команд, значение кода завершения равно нулю. В противном случае, если команда закончилась не удачно, код завершения не равен нулю. # Количество полученных параметров. $ Номер данного процесса. Поскольку для каждого процесса существует свой номер, то эта макропеременная часто используется для создания уникальных имен временных файлов. Например: ps a >&gt;/tmp/ps$$ . . . rm /tmp/ps$$ ! Номер последнего процесса, запущенного в качестве фоно- вого. - Текущие ключи (установленные режимы) интерпретатора sh типа -x и -v. Перечисленные далее макропеременные языка SHELL, имеют для системы особый смысл и не должны использоваться в других целях: MAIL Перед тем как выдать первую подсказку интерпретатор просматривает файл, имя которого является значением этой макропеременной. Если данный файл изменялся с момента последнего просмотра, будет выданно сообщение you have mail (вам пришла почта). Значение этой мак- ропеременной обычно устанавливается при выполнении файла .profile. Например: MAIL=/usr/mail/nata HOME Имя справочника для команды cd без параметров. Поиск файлов, имена которых не начинаются с символа /, - 10 - осуществляется в текущем справочникe. Для смены теку- щего справочника применяется команда cd. Например, команда: cd /usr/nata/bin назначает текущим справочник /usr/nata/bin. Команда: cat show выводит на терминал содержимое файла show из справоч- ника /usr/nata/bin. Команда cd без параметров эквива- лентна команде: cd $HOME значение этой макропеременной также обычно определя- ется в файле .profile. PATH Эта макропеременная определяет список справочников, просматриваемых при поиске команды. Если значение макропеременной PATH не определено, то принимается следующий порядок просмотра: текущий справочник, спра- вочник /bin и справочник /usr/bin. При явном задании значения макропеременной PATH имена справочников раз- деляются символом :. Например: PATH= :/usr/nata/bin:/bin:/usr/bin означает, что просмотр справочников будет вестись в следующем порядке: текущий справочник (пустая позиция перед первым символом :), /usr/nata/bin, /bin и /usr/bin. Таким образом, конкретные пользователи могут иметь свои личные команды, доступные независимо от того, какой справочник является текущим. Если имя команды начинается с символа / (т.е. заданно полное имя исполняемого файла), то поиск в справочниках не ведется. В этом случае делается всего одна попытка выполнить указанную команду. PS1 Подсказка интерпретатора (по умолчанию для обычного пользователя - $). PS2 Подсказка интерпретатора, означающая продолжение ввода (по умолчанию >&gt;). IFS Множество символов-разделителей, интерпретируемых как пробелы. - 11 - TERM Тип связанного с процессом терминала. 2.8. Выдача подсказок При работе с терминала, когда интерпретатор готов при- нять следующую команду, по умолчанию выдается подсказка $. Она может быть изменена командой: PS1=ввод: после выполнения которой подсказка будет иметь вид строки ввод:. Если введенная строка содержит синтаксически незавер- шенную конструкцию, для продолжения ввода интерпретатор выдаeт в качестве подсказки символ >&gt;. Подсказка, обозначаю- щая продолжение ввода, может быть изменена с помощью команды присваивания нового значения макропеременной PS2. Например, команда: PS2=Продолжение: установит в качестве подсказки строку Продолжение:. 2.9. Составные команды Существует два способа объединения нескольких команд в одну составную команду: { список_команд; } (список_команд) В первом случае указанный список_команд просто выполняется. Во втором - заданный список_команд тоже выполняется, но уже как отдельный процесс. Например, конструкция: (cd x; rm junk) выполняет команду rm junk в справочнике x, не изменяя теку- щего справочника, а команды { cd x; rm junk; } дают тот же самый результат, но справочник x становится текущим. 2.10. Встроенные команды Как правило, при выполнении какой-либо команды интерп- ретатор порождает отдельный процесс. Однако, существует ряд - 12 - функций, выполнение которых в качестве отдельного процесса либо неэффективно, либо невозможно. Прежде всего это отно- сится к командам, выполнение которых зависит от состояния локальных переменных интерпретатора. Команды, выполняющиеся непосредственно интерпретатором (без порождения процесса), называются встроенными командами языка. С точки зрения пользователя встроенные команды практически не отличаются по своим свойствам от остальных команд системы, за исключением того, что для них обычно нельзя переопределить стандартные файлы ввода/вывода. Далее приводится список встроенных команд с кратким описанием выполняемых функций: : Эта команда не выполняет никаких действий, ее код завершения равен нулю. Тем не менее производится подс- тановка значений макропеременных. . файл Считывает и выполняет команды из файла. Для нахождения справочника, содержащего файл, используется макропере- менная PATH. cd [справочник] Объявить указанный справочник текущим. Если параметр не задан, в качестве имени справочника используется значение макропеременной HOME. Синонимом команды cd является команда chdir. eval [команда ...] Выполняются все макроподстановки, после чего, слово eval отбрасывается и остальные символы обрабатываются как обычная командная строка. exec [команда ...] Текущий процесс замещается процессом выполненя указан- ной команды. Допускается переопределение стандартных файлов ввода/вывода. exit [N] Прерывание выполнение текущего процесса. Сообщается код завершения N. Если параметр N отсутствует, то используется код завершения последней выполненной команды. export [имя ...] Перечисленные макропеременные автоматически вводятся в среду порождаемых процессов. Если параметры не заданы, выдается список экспортируемых макропеременных. login [параметр ...] Регистрация пользователя в системе без создания нового процесса (эквивалент команды exec login параметр ...). - 13 - newgrp [параметр ...] Замена текущего идентификатора группы пользователей (эквивалент команды "exec newgrp параметр ..."). read имя ... Из стандартного файла ввода считывается одна строка. Затем макропеременным имя ... последовательно присваи- ваются значения слов, составляющих эту строку. Код завершения команды равен нулю во всех случаях, кроме тех, когда список параметров длиннее, чем число слов в считанной строке. readonly [имя ...] Запрещается переопреление перечисленных макроперемен- ных. Если параметры не заданы, выдается список всех макропеременных, определенных как readonly (только для чтения). set [-ekntuvx [параметр ...]] Устанавливает режимы работы интерпретатора языка SHELL. Могут задаваться следующие ключи: -e В неинтерактивном режиме вызывает немедленное пре- рывание процесса при обнаружении ошибки в выполне- нии команды. -k Все определенные макропеременные экспортируются в среду запускаемых процессов. -n Производит только синтаксический контроль команд. -t Прерывает выполнение процесса после того, как будет считана и выполнена одна команда. -u Устанавливает режим диагностики ошибки при попытке использовать неопределенные макропеременные. -v Устанавливает режим печати вводимых строк. -x Распечатывает команды и их параметры по мере выполнения. - Отменяет ключи -v и -x. Установленные ключи содержатся в макропеременной -. Остальным параметрам команды set присваиваются значения позиционных параметров "1, 2, ...". Если параметры не заданы, печатается список значений всех макроперемен- ных. shift Позиционным параметрам "2, 3, ..." присваиваются значе- ния параметров "1, 2, ..." соответственно. - 14 - times Выдается время, затраченное пользователем и системой на выполнение процесса. trap [команда] [N ...] При получении перечисленных сигналов выполняется ука- занная команда. umask [ddd] При формировании дескрипторов вновь создаваемых файлов признаки разрешение чтения и разрешение записи устанав- ливаются согласно маске ddd. Цифра '0' в соответствую- щем разряде означает установку признака. Формат маски совпадает с форматом дескриптора, задаваемым в команде chmod. Рассматриваются только те позиции, которые определяют разрешение чтения записи rw. Если параметр отсутствует, выдается текущее значение маски. Напри- мер, команда umask 000 установит режим, при котором всем порождаемым файлам будет устанавливаться признаки разрешения чтения записи для всех пользователей. wait [N] Ожидает окончания выполнения процесса с номером (N) и присваивает его код завершения макропеременной ?. 3. КОМАНДНЫЕ ФАЙЛЫ Последовательность команд можно записать в файл и выполнить, указав имя этого файла. Таким образом, обеспечи- вается возможность создания достаточно сложных программ на языке SHELL. В языке существуют операторы управления (опе- ратор цикла, условного перехода, выбора) и аппарат передачи параметров. Выполнение командного файла может осуществляться двумя способами. В первом случае, указывается имя интерпретатора языка SHELL - sh, режимы его работы, имя и параметры команд- ного файла. Во втором - только имя файла и параметры (ана- логично вызову любой команды системы). При этом предполага- ется, что файл имеет признак "выполнение разрешено". Результат работы команды не зависит от способа ее выполнения, поэтому, как правило, используется второй вари- ант. Запуск команды с явным указанием имени интерпретатора часто применяется для отладки командных файлов, когда необ- ходимо задавать различные режимы работы sh. Например, команда: sh file [параметры] вызывает интерпретатор для выполнения команд из файла file. Если в командной строке заданы параметры, они передаются - 15 - порождаемому процессу в виде значений макропеременных "1", "2" и т.д. Например, если файл wg содержит строку: who | grep $1 то команда sh wg nata выполняет действие эквивалентное who | grep nata Признак того, что файл можно выполнять обычно устанав- ливает компонента, создавшая данный файл (например компиля- тор). Командные файлы, как правило, создаются непосредст- венно пользователем и данного признака не содержат. Поэтому возникает необходимость установить для файла признак выпол- нение разрешено. Для этого можно использовать команду chmod. Например, в результате работы команды: chmod +х wg файл wg получает признак выполнение разрешено. Обработка параметров при запуске команды выполняется по следующим правилам: - Обрабатываются все имеющиеся метасимволы языка. - Командная строка разбивается на слова - последователь- ности символов, не содержащие символов-разделителей, к которым относятся пробел, символ начала строки и знак табуляции. Если в качестве параметра требуется пере- дать текст, который содержит пробелы, он берется в кавычки. - Выделенные слова последовательно присваиваются макропе- ременным с именами "0", "1", "2", и т.д. - В качестве значения макропеременной "#" устанавливается число параметров. - Значения всех параметров (за исключением нулевого) присваиваются макропеременой *. Т.е. макровызов $* будет заменяться на строку, содержащую значения всех параметров. Например, если командный файл show имеет вид: - 16 - echo ' Команда $0 =' $0 ' Значение $1 =' $1 ' Значение $2 =' $2 ' Число параметров =' $# ' Значение $* =' $* то в результате выполнения команды: show первый второй будет получен следующий текст: Команда $0 = show Значение $1 = первый Значение $2 = второй Число параметров = 2 Значение $* = первый второй 3.1. Комментарии В командной строке языка SHELL можно использовать коммента- рий, который служит для улучшения читаемости командных фай- лов. Комментарий должен начинаться символом # и распола- гаться в конце командной строки. Так как часть строки, сле- дующая за символом #, не рассматривается интерпретатором, в ней могут встречаться любые символы. Например: # Это пример комментария ls # Будет выполнена команда # ls (это тоже комментарий) Следует помнить, что если # является первым символом файла, ему придается особый смысл - это признак того, что должен использоваться интерпретатор языка csh. 3.2. Команда test Команда test, хотя и не является конструкцией языка SHELL, необходима при создании командных файлов. В резуль- тате выполнения команды осуществляется проверка заданного условия и сообщается код ее завершения, который может использоваться в операторах условного перехода и цикла. Например, код завершения команды test -f file равен нулю, если файл file существует, и не равен нулю - в противном случае. - 17 - Основные возможности команды можно проиллюстрировать на следующих примерах: test s истинно, если аргумент s не является пустой строкой; test -f file истинно, если файл существует; test -r file истинно, если файл можно читать; test -w file истинно, если в файл можно писать; test -d file истинно, если файл является справочником. 3.3. Оператор for В языке SHELL существует возможность последовательного повторения какой-либо группы команд для каждого элемента указанного списка. Для этой цели используется оператор цикла for, который имеет следующий формат: for имя [in слово1 слово2 ...] do список_команд done где список_команд - это последовательность одной или нес- кольких простых команд, разделенных символами ; или перечис- ленных на разных строках. Зарезервированные слова do и done распознаются только в том случае, если они следуют за симво- лом новой строки или точки с запятой. Имя - это макропере- менная языка SHELL, которая в процессе выполнения списка_команд последовательно принимает значения слово1 слово2 .... Если конструкция in слово1 слово2 ... отсутст- вует, то цикл выполняется один раз для каждого заданного параметра (т.е. по умолчанию предполагается in $*). В качестве примера можно привести команду tel, которая прос- матривает файл /usr/lib/pfone, содержащий строки вида: ... Иванов И.И. 224 01 01 Петров П.П. 123 07 07 Сизов В.И. 224 44 94 ... Текст процедуры tel: for i do grep $i usr/lib/pfone; done - 18 - В результате выполнения команды: tel Петров будут напечатаны те строки файла /usr/lib/pfone, которые содержат последовательность символов Петров, а команда: tel Иванов Петров напечатает сначала строки, содержащие последовательность символов Иванов, а затем те строки, которые содержат символы Петров. Еще одним примером использования цикла for является командный файл create: for i do >&gt; $i; done Результатом выполнения команды create alpha beta является создание двух пустых файлов alpha и beta. 3.4. Оператор case Рассмотрим в качестве примера командный файл add, содержащий следующий текст: case $# in 1) cat >&gt;>&gt; $1;; 2) cat >&gt;>&gt; $2 <&lt; $1;; *) echo 'Формат: add [откуда] куда';; esac При вызове команды с одним аргументом, например: add file параметр $# получает значение '1', и команда cat копирует информацию из стандартного файла ввода в конец файла file. Команда: add file1 file2 допишет содержимое файла file1 в конец файла file2. Если число параметров, передаваемых команде add, отлично от 1 и от 2, то печатается сообщение "Формат: add куда [откуда]". Формат оператора case: - 19 - case слово in [образец[|образец] ...) список_команд;;] ... [образец[|образец] ...) список_команд[;;]] esac Интерпретатор последовательно сравнивает слово с каждым из указанных образцов. При обнаружении соответствия выполня- ется записанный при образце список_команд, после чего, обра- ботка оператора завершается. Символ * представляет собой образец, который соответствует любой строке. Каждый список_команд (за исключением последнего) необходимо завер- шать символами ;;. Первое же совпадение слова с образцом полностью опреде- ляет множество выполняемых команд. В следующем примере команды, указанные за вторым символом *, не будут выпол- няться никогда: case $# in *) ...;; *) ...;; esac Оператор case часто используется для проверки коррект- ности параметров. Это можно проиллюстрировть следующим фраг- ментом команды cc: for i do case $i in -[ocs]) ...;; -*) echo 'неизвестный ключ $i';; *.c) lib/c0 $i ...;; *) echo 'неизвестный параметр $i';; esac done Если условием выполнения какого-либо списка_команд является группа образцов, то при их перечислении в команде case в качестве разделителя используется символ |. Так, оператор: case $i in ) echo $i -y) echo $i esac может быть записан слудующим образом: - 20 - case $i in -х|-y) echo $i esac При поиске соответствующего образца применимы основные соглашения об отмене специального значения метасимволов, так образец в конструкции: case $i in ?) ... будет соответствовать символу ?. 3.5. Операторы while и until Оператор while предназначен для организации циклов, выполнение которых производится до тех пор, пока код завер- шения указанного списка команд равен нулю. Общая форма оператора while: while список_команд_1 [do список_команд_2] done В каждом цикле выполняются команды из списка_команд_1. Оператор while проверяет код завершения последней простой команды из этого списка: если он равен нулю, выполняется список_команд_2 и цикл повторяется, иначе - выполнение цикла завершается. Например, при выполнения следующих операторов: while test $1 do ... shift done и for i do ... done будет получен одинаковый результат. Оператор shift переименовывает позиционные параметры "2, 3, ..." в параметры "1, 2, ..." соответственно; значение параметра "1" теряется. - 21 - Другим способом организации цикла является использова- ние оператора until: until список_команд_1 [do список_команд_2] done В отличие от while цикл until будет выполняться до тех пор, пока код завершения последней команды списка_команд_1 не будет иметь нулевое значение. 3.6. Операторы break и continue Операторы break и continue используются в конструкциях for, while и until. Оператор break прерывает работу цикла, в теле которого он выполняется. В качестве примера можно привести прог- рамму, которая выдает значения своих параметров, расположен- ных до символа %: for i do case $i in %) break;; *) echo $i;; esac done Оператор continue осуществляет переход к следующей ите- рации цикла. Для примера рассмотрим командный файл, который выводит только те параметры, которые начинаются с буквы: for i do case $i in [А-Яа-я]*) echo $i;; [A-Za-z]*) echo $i;; *) continue;; esac done 3.7. Оператор if Условный оператор вида: if список_команд_1 then список_команд_2 [else список_команд_3] fi - 22 - проверяет код завершения последней простой команды списка_команд_1: если он равен нулю, выполняется список_команд_2, иначе - список_команд_3. Команда if может использоваться совместно с командой test, например, для проверки существования файла: if test -f $1 then echo "ФАЙЛ $1 СУЩЕСТВУЕТ" else echo "ФАЙЛ $1 НЕ СУЩЕСТВУЕТ" fi При многократном повторении условного оператора, напри- мер: if ... then ...