Стандартная командная оболочка - это язык программирования, действиями которого (в основном) являются вызовы «утилит», которые являются исполняемыми программами. Задача, которую выполняет оболочка, - настроить стандартную среду для вызова утилиты, которая включает в себя:
Выяснение, какой исполняемый файл соответствует вызываемой утилите;
Назначение файловых дескрипторов stdin, stdout и stderr для утилиты соответствующим потокам;
Создание вектора аргументов argv
и передача его вызванной утилите;
Настройка environ
global утилиты, доступ к которой утилита может получить через getenv
стандартную библиотечную функцию;
Как и любой язык программирования, оболочка имеет значения, литералы, переменные и поток управления. У него есть синтаксис (и очень идиосинкразический алгоритм лексического анализа). У него также есть другие примитивы, специально разработанные для его задачи.
Например, /usr/bin
и "this is not a sentence"
являются буквальными значениями в языке оболочки. Кавычки вокруг второго из них не являются частью стоимости; они являются частью синтаксиса языка для буквальных строк. (Язык оболочки позволяет записывать многие буквальные строки без кавычек, а также включает сложный язык выражений, так что не все строки в двойных кавычках являются литералами, но в простом случае строка в кавычках концептуально не отличается от строки в кавычках в C .)
Базовый синтаксис и семантика стандартизированы Posix. Многие широко используемые языки оболочки в основном соответствуют этому стандарту. Почти все имеют расширения; некоторые (если не большинство) не полностью совместимы даже с базовым стандартом, если не включены определенные параметры. (Например, для bash
, вызывая его с аргументом командной строки --posix
.) Однако, как правило, соблюдаются основные принципы, и чтение приведенной выше ссылки Posix предоставит хороший обзор. Включает полную грамматику.
В целом процедура следующая:
- Оболочка разбивает командную строку на «слова».
- Некоторые слова «расширены», возможно, заменены ноль или более слов.
- Некоторые слова интерпретируются как перенаправление файлового дескриптора; другие как назначения переменных среды.
- Если результатом является определенный синтаксис оболочки, он выполняется. В противном случае первое слово интерпретируется либо как имя функции оболочки, либо как встроенная команда, либо как внешняя утилита.
- Если команда разрешается во внешнюю утилиту, слова из командной строки (кроме тех, которые уже используются как перенаправления и назначения) помещаются в вектор
argv
, и утилита вызывается.
Это намного сложнее, но это основная модель.
Вызов утилиты выполняется с использованием одной из exec*
семейства стандартных библиотечных функций, которая принимает в качестве аргументов:
- Путь к исполняемому файлу
- Вектор указателей на строки с нулевым завершением, который будет вектором
argv
- Вектор с нулевым завершением указателей на строки формы
name=value
, который будет environ
глобальным.
Затем вызов exec
вызывает внешнюю утилиту. Он копирует вектор аргументов и список окружения в адресное пространство утилиты, но не изменяет и не проверяет значения иначе, кроме проверки того, что общий размер двух списков не превышает некоторый системный предел.
Остальная часть этого ответа относится к тому, как сама утилита (может или должна) анализировать вектор аргументов, который она получает.
Не существует стандарта для интерпретации аргументов командной строки, но есть рекомендации и стандартные (и не очень стандартные) библиотечные подпрограммы, которые навязывают своего рода стандарт де-факто, который определяет, чего (могут) ожидать пользователи.
Начнем с того, что правила Posix (в основном) выполняются стандартная функция Posix getopt. Эти рекомендации предполагают, что необязательные аргументы (с -
флагами) предшествуют всем позиционным аргументам.
Однако не все утилиты Posix соответствуют этим предложениям, и часто встречаются утилиты, которые «переставляют» аргументы, позволяя параметрам следовать позиционным аргументам. Этот механизм (в основном) реализован версией getopt для Gnu. . Кроме того, Gnu определяет (и предлагает использовать) getopt_long функция, которая позволяет использовать многозначные параметры, инициированные с --
.
Во всех случаях, как анализируются необязательные аргументы флага, зависит от того, определена ли опция как принимающая аргумент или нет. Так
-s1 word
можно разобрать как:
- If
-s
takes an argument:
- option
-s
with argument "1"
- позиционный аргумент "слово"
- If
-s
does not take an argument and -1
is a valid flag not taking an argument
- option
-s
- вариант
-1
- позиционный аргумент "слово"
- If
-s
does not take an argument and -1
does take an argument:
- option
-s
- вариант
-1
с аргументом "слово"
В дополнение к вышеперечисленному, существуют также команды, которые принимают «длинные параметры», начинающиеся с одного дефиса (и, таким образом, не позволяют объединить короткие параметры в одно слово). Это стиль, используемый TCL, за которым следуют многие команды графического интерфейса. Этот стиль можно проанализировать с помощью функции GNU getopt_long_only
(см. Предыдущую ссылку).
person
rici
schedule
04.06.2015
>
- это ваше приглашение, если вы введете ввод, я думаю, что'
не будет совпадать с"
, и поэтому оболочка может вызвать ошибку - person Eregrith   schedule 04.06.2015argv
? Например.for (int a = 0; a < argc; ++a) printf("argv[%d] = %s\n", a, argv[a]);
- person Some programmer dude   schedule 04.06.2015"
и'
. - person Keith Thompson   schedule 04.06.2015"
и'
в вашем примере было опечаткой, я предлагаю вам отредактировать вопрос, чтобы исправить это. Как оболочка преобразует командную строку в массивargv
- это другой вопрос, чем анализ массиваargv
после запуска программы. - person Keith Thompson   schedule 04.06.2015C
, а заголовок и тег вводят в заблуждение. Просьба уточнить. (Если вы считаете, что эту работу выполняет служебная программа или вызов exec, значит, ваша модель неверна.) - person rici   schedule 04.06.2015name
с предшествующей опцией-s
. Я думаю, вы пытаетесь спросить, как строка командной строки разбивается на элементы массива, на который ссылаетсяargv
. Спроси об этом. - person Keith Thompson   schedule 04.06.2015