Inferno OS Wiki
Регистрация
Advertisement


ИМЯ

sh, builtin, exit, load, loaded, local, whatis, quote, run, set, unload, unquote - командный язык

РЕЗЮМЕ

sh [-ilxvn ] [ -c команда ] [ файл [ аргумент ... ]

ОПИСАНИЕ

Sh программируемый интерфейс пользователя (оболочка) для Inferno. Он выполняет строки команд набранные в терминале или из файла, или если он используется с флагом -c, из списка аргументов. Его также можно использовать для добаления программной функциональности модулям Limbo (смотри sh(2))

Командная строка[]

Командная строка это последовательность команд разделенных символами амперсанд или точка с запятой (& or ;), и ограниченная символом новой строки. Команды выполняются в поледовательности слева направо. Sh не ожидает окончания выполнения команды сопровождаемую знаком & перед тем выполнить новую команду. Всякий раз, когда команда сопровождаемая & выполняется, ее идентификатор процесса назначается переменной оболочки $apid. Когда же команда не сопровождаемая знаком & заканчивает свое выполнение или прерывается, переменная оболочки $status содержит сообщение process's wait (смотри prog(3)); или же это будет пустая строка если команда завершилась успешно.

Символ (#) и все следующие за ним символы до конца строки (но не включая ее) игнорируются за исключением кавычек.

Простые команды[]

Простые команды это последовательность аргументов с вкраплениями перенаправления ввода-вывода. Если первый аргумент имя встроенной команды или заключенный в скобки блок команд (смотри далее "Составные команды"), они выполняются интерпретатором. Если первый символ имени скобка ({), интерпретатор пытается распознать и выполнить блок команд, если распознавание не удалось, возникает исключение. Иначе sh ищет внешнюю программу для выполнения.

Если имя заканчивается на .dis, sh ищет Dis модуль с тем же именем; в противном случае он во-первых пытается найти модуль Dis в названии которого есть .dis и если это не удается, ищет исполняемый файл с тем же имененм, который должен быть скриптом доступным для чтения и исполнения. Если имя не начинается с символа обратной черты (/) или точка-слэш (./), тогда поиск имени начинается относительно каталога /dis и затем относительно текущего каталога. Модуль Dis будет выполнен только если он реализует Командный Интерфейс (см. sh(1)); файл-скрипт будет выполнен только если он начинается с символов `#!` сопровождаемые именем исполняемого файла подчинающегося правилам указанным выше. В этом случае команда будет выполнена с с любыми последующими аргументами указанными в заголовке #!, сопровождаемые путем к файлу скрита, сопровождаемые любым количеством аргументов переданных команде.

Например, выполняя простую команду ls, sh ищет одну из следующих вещей, в указанном порядке, прекращая поиск если совпадение найдено:

# встроенная команда называется `ls`.# модуль Dis называется `/dis/ls.dis`,# исполняемый скрипт называется `/dis/ls`,# модуль Dis называется `./ls.dis`,# исполняемый скрип называется `./ls`.

Аргументы и переменные[]

Несколько конструкций могут использоваться в когда синтаксис sh ожидает появление аргумента. Во многих случаях составное значение будет списком аргументов, предпочтительнее чем обычная строки.

Простейшим видом аргументов будет слово не заключенное в кавычки: последовательность одного или более символов которая не содержит пробелов, символов табуляции, перевода строки или любого изследующих символов:

# ; & | ^ $ ` ' { } ( ) < > " =

Не заключенное в кавычки слово содержащее любой из символов * ? [ является шаблоном для соответствия именая файлов. Символ * заменяет любую последовательность символов, ? соответствует любому одиночному символу, и [класс] соответствует любому символу из класса. Если первый символ класса ^, класс дополнен (Поскольку этот символ особенный в интерпретаторе, он может быть включен в щаблон если этот символ заключен в кавычки, в то время как [ перед ним не в кавычках). Класс так же может содержать пару символов разделунных знаком -, заменяя собой все символы лексически расположенные между ними. Символ / дожен появляться только в шаблоне. Шаблон заменяется списком аргументов, по одному на каждое совпавшее имя, за исключением того, что в случае если шаблон не соответствует ни одному имени он не заменяется на пустой список. Соответствие шаблону выполняется после других операций.

x=/tmp; echo $x^/*.b

соответствует /tmp/*.b, а не /*.b которое потом предворяет /tmp.

Слово в кавычках это последовательность символов окруженная одиночными кавычками ('). Одиночная кавычка может быть представлена окруженной двойными кавычками ().

Каждый из следующих является аргументом.

(arguments)
Значение последовательности аргументов заключенных в скобки состоит из списка включенных в него членов каждого из элементов последовательности. Список аргументов не является рекурсивными, хотя его синтаксис может показаться таковым. Последующие выражения совершенно идентичны.
echo hi there everybody
((echo) (hi there) everybody)
echo (hi there everybody )

Переводы строк внутри скобок считаются за обычный пробел, они не завершают команду. Это может оказаться полезным и дать больше свободы в разметке (расположении, размещении) комманд, принимающих в качестве аргументов несколько других команд, например, несколько подобных команд определены в sh-std(1).

$argument
Аргумент следующий за $ это имя переменной значение которой будет подставлено вместо имени. Возможны многоуровневые вложения. Значения переменных это списки строк. Если аргумент является числом n, значение n-ного элемента переменной $*, пока у $* не будет n элементов, в этом случае значение будет пустым. Присвоение переменным описывается ниже в разделе Присвоение.
$#argument
Эта переменная возвращает количество элементов в именованной переменной. Переменной никогда не назначается значение имеющее ноль элементов.
$" argument
Значением является строка содержащая компоненты именованной переменной разделенные пробелами. Переменная с нулевым количеством элементов порождает пустоую строку.
`{command}
"{ command }
Sh выполняет команду и считывает ее стандарный вывод. В случае использовании обратной кавычки (`), он разбивается на список аргументов, используя символ $ifs как сепаратор. Если переменная $ifs не установлена, будет использовано значение ' \t\n'. В случае применения двойной кавычки ( " ) разбиение на список (токенизация) не будет сделана.
argument^argument
Оператор ^ соединает (производит конкатенацию) два операнда. Если два операнда имеют одинаковое число компонентов, они соединяются попарно. В противном случае, один операнд должен иметь один компонент а другой должен быть не пустым, и конкатенация будет разделительной.
${command}
Команда должна быть простой, не содержащей перенправлений, ее первое слово дожно быть имененм встроенного оператора. Опретор будет вызван и его значение будет подставлено в выражение. Смотрите ниже раздел Встроенные Команды для побробной информации.
<{command}
>{command}
Команда выполняется асинхронно с перенаправленным стандартным вводом или выводом подключенного канала. Значением аргумента является имя файла ссылающегося на на другой конец канала. Таким образом можно сконструировать нелинейные каналы. Например, здесь заупускаются две команды old и new, а cmp сравнивает их вывод.
cmp <{old} <{new}

Free Carets[]

Свободная конкатенация (унаследовано от Plan9 rc) в большинстве случаев, sh будет вставлять оператор ^ между словами автоматечески между теми словами которые не разделены пробелом. Всякий раз, когда появляется один из символов $ ' ` и следующее за ним слово в кавычках или без; или слово в кавычках или без не содержащие пробелов и табуляции, символ ^ будет вставляться между ними. Если же слово не заключенное в кавычки непосредственно следующее за $ содержит символ отличный от арифметического, или подчеркивания _ , или *, символ ^ будет вставлен таким первым символом. Как в случае:

limbo -$flags $stem.b

равносильно

limbo -^$flags $stem^.b

Присваивание[]

Команда в виде name=value или name:=value присваивает значение переменной окружения с указанным именем. Значением могут являться как список аргументов, так и присваиваемое выражение. Если используется := , значение сохраняется в локальной области видимости. Локальная область видимости значений создается всякий раз при вхождении в блок команд заключенных в скобки, и разрушается когда блок покидается. Если использован = , значение сохраняется в текущей области видимости (текущей из всех вложенных) содержащей определение имени переменной.

Список имен так же может быть использован вместо имени, это будет причиной того, что каждый элемент значения окажется присвоенным соответствующему имени переменной в списке. Последняя переменная в списке назначается любому любому заключительному элемента в левой части. В случае, если имен переменных больше чем элементов значений, оставшимся элементам будет присвоен пустой список. Например, после присвоения:

(a b c) = one two three four five

$a присваивается one, $b становится two, и $c содержит оставшиеся три элемента (three four five).

Перенаправления ввода-вывода[]

Выражение >file перенаправляет файл стандартного вывода (файловый дескриптор которого равен 1, обычно это терминал) в именованный файл; >> file добавляет стандартный вывод в файл. Стандартный файл ввода (файловый дескриптор равен 0, так же терминал) может быть перенаправлен из файла выражением file, которое открывает файл на чтение и на запись. Обратите внимание на то, что если в роли файла выступает заключенный в кавычки блок, перенаправление будет обработано как канал к указанной команде - и считается идентичным оператору <{} описанному выше.

Перенаправления могут применяться к фаловому дескриптору отличному от ввода или вывода путем передачи числового параметра заключенного в квадратные скобки оператору перенаправления. Например, диагностический вывод (фаловый дескриптор 2) может быть перенаправлени следующим выражением:

limbo junk.b >[2] junk.

Файловый дескриптор может быть перенаправлен в уже открытый файл при помощи >[fd0=fd1] или <[fd0=fd1]. Fd1 это дескриптор ранее открытого файла и fd0 становится его новой копией (sys-dup(2)).

Перенаправления исполняются слева направо. Поэтому

limbo junk.b >/dev/null >[2=1]

и

limbo junk.b >[2=1] >/dev/null

приводят к разным результатам: в первом случае стандартный вывод перенаправляется в /dev/null и затем перенаправляет туда же диагностический вывод, во втором случае диагностический вывод посылается на терминал ипосылает стандартный вывод на /dev/null.

Составные команды[]

Пара команд разделенных оператором канал/труба (|) это команда. Стандартный вывод левой команды посылается на стандартный ввод правой команде. Оператор канал может быть употреблен с файловыми дескрипторами. |[fd] соединяет выходной конец канала с указанным дескриптором fd отличным от 1. |[fd0=fd1] соединяет вывод fd1 левой команды и вход fd0 правой команды.

Последовательность команд разделенных &, ;, или новой строкой можно сгруппировать заключив их в фигурные скобки ({}), ранее названные блоком в скобках. Блок в скобках может использоваться везде, где ожидается одно слово. Если простая команда найдена в блоке в качестве первого слова, пременной $* присваиваются все последующие аргументы, $0 устанавливается полностью всем блоком, и команды последовательно исполняются. Если блок передан в качестве аргумента, исполнения не происходит: блок конвертируется в функционально эквивалентную строку, подходящую для последующей ре-интерпретации оболочкой. Нулевая команда ({}) не имеет никакого эффекта и всегда возвращает статус nil. Например, все следующие команды производят одинаковый результат:

echo hello world
{echo hello world}
'{echo hello world}'
{echo $*} hello world
sh -c {echo hello world} {$*}
{echo hello world} {$*}
{{$*} {echo hello world}}
"{echo {echo hello world}}
'{echo hello' ^ ' world}' x := {echo hello world}; $x

Важно отметить что значение переменной $* теряется всякий раз когда производится вхождение в блок, так например, следующая команда напечатает пустую строку:

{{echo $*}} hello world

Встроенные команды[]

Термин "встроенная команда" использовался уже кое-где в этом документе для ссылки на команды прямо выполняющиеся интерпретатором; большинство встроенных команд определены внешне загруженными модулями; существует несколько команд которых это не касаетя, известных как "внутренние" встроенные команды, перечисленные ниже.

Принимая во внимание способность sh обрабатывать составные команды (заключенные в скобки) как аргументы других команд, большая функциональность по управлению ходом выполнения, традиционно жестко вшитая в интерпретатор, в sh реализована в загружаемых модулях. Смотри подробности в sh-std(1), sh-expr(1), и sh-tk(1).

Существуют два класса встроенных команд: первый класс ивестный как "встроенные", используется также как обычные команды, с той лищь разницей что встроенные команды могут вызывать исключения, тогда как внешние команды не могут, потому что они запускаются в отдельном процессе. Втророй класс, извустный как "встроенные подстановки" может быть использован как первое слово в команде в операторе ${}. Эти два класса существуют в различных пространствах имен: встроенная команда может делать совершенно другое нежели чем "встроенная подстановка" с тем же самым именем.

В основном, нормальные встроенные команды выполняют некоторые действия или проверку неких условий; возвращая статус нормальной встроенной команды, обычно указывая код ошибки или успешное выполнение. Роль встроенных подстановок выдать занчение (возможно даже список) который подставляется в это место как список аргументов команды.

команда @
Выполняет команду в подпроцессе (subshell) позволяя к примеру, создать копию пространства имен и работать с ним независимо от основного командного интерпретатора.
run имя_файла ...
Выполнить команды из файла. Переменной $* присваивается оставшаяся части списка аргументов следующая за именем файла.
builtin команда ...
Команда выполняется как обычно, за исключением того, что любая команда определенная во внешнем модуле игнорируется, таким образом достигается изначально запланированноеповедение команды. Эта команда не может быть переопределена внешним модулем.
exit
Прерывает текущий процесс
load путь ...
Команда load пытается загрузить каждый свой аргумент как модуль в интерпретатор. Если модуль был успешно загружен, каждая встроенная команда определенная в модуле добавляется к списку встроенных команд. Если же существовало предыдущее определение команды, то она замещается исключение составляют встроенные в sh команды, которые скрываются и возникают вновь, когда модуль выгружается Если модуль с тем же путем был загружен то sh не будет пытаться загрузить его еще раз. В случае если путь не начинается с "/" или "./", интерпретатор просматривает стандартныйкаталог со встроенными модулями /dis/sh в поисках этого модуля.Если загрузка не удалась будет вызвано исключение ("bad module").

Переменная $autoload может содержать список модулей которые интерпретатор будет загружать автоматически во время своей инициализации. (Модуль загружается когда создается новый контекст:Sh->Context. Подробности смотри в sh(2))

unload путь...
Выгружает загруженные ранее модули, отменяя (если они были) изменения в командах. Для успешного выполнения, путь должен быть тем же самым, как в момент осществления загрузки.
loaded
Выдает список встроенных команд определенных в настоящий момент, предварительно сопровождая именем модуля где команда была определена. Внутренне определенные команды отмечены модулем builtin.
whatis имя ...
Напечатает значение каждого имени в форме пригодной для sh.

Форма следующая:

varname = value...
Varname это не пустая переменная окружения.
loadmodule; имя
Имя определяется как встроенное внешним загруженным модулем.
loadmodule;${name}
Имя определяется как встроенное замещение внешним загруженным модулем.
builtinname
Имя определяется как встроенное внутри sh.
${name}
Имя определяется как встроенное замещение внутри sh.
pathname
Полный путь внешенего файла
${builtin command }
Выполняет замещение встроенных команд что делает встроенные команды обычными

// не понял?

${loaded}
Загруженная встроенная команда производит список имен всех модулей загруженных в настоящий момент.
${quotelist}
Цитата выдается отдельным списком элементов, который будет заново обработан интерпретатором для воссоздания списка.
${bquotelist}
То же что и цитата, за исключением того что элементы списка заренее правильно сформированные командные блоки, а не цитаты.
${unquotearg}
Расквотирование (Unquote) - обратная операция квотрированию, возвращает оригинальный список значений. Список квотированный bquote может быть расквотирован обработкой интерпретатором.

Окружение[]

Окружение - это список строк которые делают возможным выполнением внешних команд модулем env (смотри env(2)). Если модуль env не существует или не загружен, то не будет никаких сообщений об ошибке, и никаких переменных не будет экспортировано во внешние команды. Sh создаст элемент окружения для каждой не пустой переменной. Они будут отформатированы так же, как если бы это было через ${quote}. Отметьте, что для того чтобы пременные были экспортированы, их имена должны быть одолетворять накладываемым ограничениям env(3), в противном случае имена не будут экспортированы.

Когда sh начинает выполнение, он считывает определния переменных из своего окружения.

Внутри sh сохраняет контекст, который содержит набор переменных окружения, текущие флаги выполнения и список встроенных модулей. Копия создается в любом случае, когда может возникнуть параллельный доступ. Это происходит с процессами выполняющимися в каналах, процессах запущенных асинхронно с помощью &, и в любой встроенной команде которая асинхронно запускает команду оболочки.

Исключения[]

Когда sh сталкивается с ошибкой обрабатывая входной поток, возникает исключение, и если установлен флаг -v, сообщение об шибке выводится на стандарный вывод ошибок. Исключение вызывает обработку текущей команды прерывая ее и управление передается назад на стек вызовов. В интерактивном интерпретаторе главный цикл обработки команд перехватывает все исключения и устанавливает в переменной $status имя исключения. Исключения не передаются между процессами. Любая команда которая ожидает перенаправление ввода/вывода запускается в отдельном процессе, именуемом каналом (|), перенаправлениями (>, <, >>, and <>), замещениями в обраных кавычках ( ` , " ) и фоновые процессы (&). Исключения могут вызываться (raised) и освобождаться (rescued) используя соответственно функции raise и rescue из встроенного стандартного модуля std. (Смотри детали в sh-std(1)).

Имена исключений вызываемых sh включают в себя:

parse error - Ошибка возникающая при попытке обработать команду

usage - Встроенной команде передан неверный набор аргументов

bad redir - Возникла ошибка при открытии файлов предварительно запущенного процесса.

bad $ arg - Неверное имя было дано оператору $ или ${} .

no pipe - Sh не удалось создать канал

bad wait read - Возникла ошибка ожидания на выходе из процесса

builtin not found - Встроенная команда была назначена но не найдена

Специальные переменные[]

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

$*
Устанавливает список аргументов во время инициализации. Как только ограниченный скобками блок будет выполнен текущее значение сохраняется и $* получает новый список аргументов. Сохраненное значение восстанавливается по выходу из блока.
$apid
В том случае, если процесс запущен асинхронно при помощи &, в $apid устанавливется идентификатор процесса.
$ifs
Разделитель полей ввода используемый в замещении при использовании обратных кавычек. Если $ifs не установлен в окружении sh, она будет проинициализирована пробелом, табуляцией или символом новой строки.
$prompt
Когда sh выполняется интерактивно, первый компонент $prompt печатается перед считыванием каждой команды. Второй компонент печатается если встречен символ новой строки и больше строк требуется для завершения команды. Если переменная не установлена в окружении, она инициализируется строкой prompt=('% ' ).
$status
Устанавливается в сообщение-ожидания последней выполненнойпрограммы, статус возврата последней выполненной встроенной команды (кроме запущенной с &), или именем последнего вызванного исключения, в зависимости от того что поизойдет раньше. Когда sh достигает конца файла своего ввода, переменная $status соответствует статусу выхода.

Вызов[]

Если sh запущен без аргументов, он читает команды из стандартного ввода. Иначе перевый нефлаговый аргумент будет файлом из которого проичтаются команды (так же смотрите опцию -c ниже). Все последующие аргументы станут начальным значением переменной $*. Sh принимает следующие флаги командной стики:
-c Читать команды из строки
-i Если указан этот флаг или sh запущен без аргументов, а его стандартный ввод это терминал, он запускается в интерактивном режиме. Приглашение берется из переменной $prompt. Эта опция устанавливает флаг -v.
-l Если указан флаг -l или первый символ нулевого аргумена это ` - `, sh читает команды из /lib/sh/profile если он существует, а затем из ./lib/profile перед тем как прочитать стандартный ввод.
-n Обычно sh разветвляет свое пространство имен при запуске; опция -n отменяет такое поведение.
-v В неинтерактивном режиме sh не печатает сообщения, идущие в стандартный вывод ошибок; флаг -v отменяет это поведение.
-x Отправлять каждую простую команду в стандартный вывод ошибок перед исполнением.

ИСХОДНЫЙ ТЕКСТ

/appl/cmd/sh/sh.y

СМОТРИ ТАКЖЕ

tiny(1), wm-sh(1), sh-std(1), sh-expr(1), sh-file2chan(1), sh-tk(1), sh-arg(1), sh-regex(1), sh-string(1), sh-csv(1), sh(2), env(2)

ОШИБКИ

Из-за недостаточной системной поддержки, дописывание в файл при помощи >> не будет работать корректно в случае нескольких конкурирующих записывающих (посмотрите примеры sh-file2chan(1) для одного из решений этой проблемы)
В случае использования командного интерпретатора как основного языка программирования, помните - он очень медленный! Задачи с интенсивной нагрузкой лучше решать в Limbo, более безопасным и полезным языком .
Advertisement