Простое расширение команд в bash

Когда выполняется простая команда, shell выполняет следующие расширения, назначения и перенаправления слева на право.

  1. Слова которые парсер отметил как заданные переменные(те, которые предшествуют имени команды) и перенаправления сохраняются для последующей обработки.

  2. Слова которые не являются заданными переменными или перенаправлением расширения. Если слова остаются после расширения, первое слово берется имя команды, а остальные слова являются аргументами.

  3. Перенаправления проводятся так, как было описано выше в статье Перенаправления в bash.

  4. Текст после «=» в каждой назначенной переменной подвергается расширению тильды, расширению параметров, подстановке команд, арифметических расширений и удалению кавычек перед назначением переменной.

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

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

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

Условные выражения в bash

Условные выражения используют команды соединения [[ и test, и [ встроенные команды для проверки файловых атрибутов, и выполнения строковых и арифметических сравнений. Выражения формируются из следующих, унарных или первичных бинаных. Если любой файловый аргумент один из primaries имеет вид /dev/fd/n то файловый дескриптор «n» проверяется. Если файловый аргумент одного из primaries является одним из /dev/stdin, /dev/stdout, или /dev/stderr файловый дескриптор 0,1, или 2 соответственно проверяются.

Если не указано иное, primaries которые работают с файлами по символичным ссылкам, действуют на цель ссылки, а не на саму ссылку.

При использовании с [[, < и > операторами сортировки лексикографически используются текущей локалью. Тестовая команда сортировки использует ASCII упорядочения.

-a file Истинно, если файл существует.

-b file Истинно, если файл существует и является специальным файлом блочного устройства.

-c file Истинно, если файл существует и является специальным файлом символьного устройства.

-d file Истинно, если файл существует и является директорией.

-e file Истинно, если файл существует

-f file Истинно, если файл существует и является обычным файлом.

-g file Истинно, если файл существует и для него установлен идентификатор группы.

-h file Истинно, если файл существует и является символической ссылкой.

-k file Истинно, если файл существует и для него установлен ‘‘sticky» bit.

-p file Истинно, если файл существует и является именованным каналом (FIFO).

-r file Истинно, если файл существует и доступен для чтения.

-s file Истинно, если файл существует и имеет размер больше нуля.

-t fd Истинно если дескриптор файла fd открыт и указыает на терминал.

-u file Истинно если файл существует и для него установлен бит смены пользователя.

-w file Истинно, если файл существует и доступен для записи.

-x file Истинно, если файл существует и является исполняемым.

-G file Истинно если файл существует и его владельцем является пользователь на которого указывает эффективный идентификатор пользователя.

-L file Истинно, если файл существует и является символической ссылкой.

-N file Истинно, если файл существует и был изменен с момента последнего чтения.

-O file Истинно, если файл существует и принадлежит текущему эффективному пользователю.

-S file Истинно, если файл существует и является сокетом.

file1 -ef file2 Истинно если file1 и file2 относятся к тому же устройству и одинаковые (inode) индексных дескрипторов.

file1 -nt file2 Истинно если file1 новее(по дате изменения) чем file2, или если file1 существует, а file2 нет.

file1 -ot file2 Истинно если file1 старше чем file2 или если file2 существует, а file1 нет.

-o optname Истинно если задана опция shell optname.

-v varname Истинно если shell переменная varname установлена(если ей было присвоено значение).

-z string Истинно, если длина строки равна нулю.

string

-n string Истинно, если длина строки не равна нулю.

string1 == string2

string1 = string2 Истинно, если строки равны. «=» Следует использовать с командой test для POSIX соответствия.

string1 != string2 Истинно, если строки не равны.

string1 < string2 Истинно если string1 лексикографически предшествует string2.

string1 > string2 Истинно если string1 лексикографически стоит после string2.

arg1 OP arg2 OP является одним из -eq, -ne, -lt, -le, -gt, или -ge. Эти арифметические бинарные операторы возвращают true если arg1 равно, не равно, меньше, меньше или равно, больше, чем, или больше чем или равно arg2 соответственно. Arg1 и arg2 могут быть положительными или отрицательными числами.

Арифметическая оценка в bash

Shell позволяет оценивать арифметические выражения при определенных обстоятельствах. Оценка производится в фиксированной ширине целых чисел без проверки на переполнение, хоть деление на 0 прерывается и отмечается как ошибка. Операторы, их приоритет, ассоциативность и значения такие же как в языке Си. Следующий список операторов сгруппирован по уровням с одинаковым приоритетом операторов. Уровни располагаются в порядке убывания приоритета.

id++ id— Переменная post-increment и post-decrement.

++id —id Переменная pre-increment и pre-decrement.

— + Унарный минус и плюс.

! ~ Логическое и побитовое отрицание.

** Возведение в степень.

* / % Умножение, деление, остаток.

+ — Сложение, вычитание.

< < >> Левый и правый побитовый сдвиг.

< = >= <> Сравнение.

== != Равенство и неравенство.

& Побитовое И.

^ Побитовое исключающее ИЛИ.

| Побитовое ИЛИ.

&& Логическое И.

|| Логическое ИЛИ.

expr?expr:expr Условный оператор.

= *= /= %= += -= < <= >>= &= ^= |= Назначение.

expr1 , expr2 запятая.

Shell переменные в качестве операндов; параметр расширения выполняется перед вычислением выражения. Внутри выражений, переменный shell могут также ссылаться на имена не используя синтаксис параметра расширения. Shell переменная null или unset оценивается в 0, когда обращается по имени, не используя синтаксис параметра расширения. Значение переменной вычисляется как среднее арифметическое выражение, когда на него ссылается или когда переменная, которой было задано целое число атрибутов с помощью declare -i присвоенное значение. Значение null вычисляется в 0. Shell переменная не должна иметь включаемый атрибут целое число, которое будет использоваться в выражении.

Константы, начинающиеся с 0, интерпретируются как восьмеричные числа. Начинающиеся с 0x или 0X обозначает шестнадцатеричное число. Кроме того, числа вида [base#]n, где base является десятичным числом от 2 до 64, представляющее арифметическое base, и «n» представляет собой число в этой base. Если base# опускается то base 10 используется. Цифры больше 9 представлены строчными буквами, заглавными буквами, @ и _ именно в таком порядке. Если base меньше или равно 36, прописные и строчные буквы могут быть использованы как взаимозаменяемые для представления чисел от 10 до 35.

Операторы вычисляются в порядке приоритета. Подвыражения в круглых скобках вычисляются первыми и могут не подчинятся правилам приоритета указанным выше.

Функции shell

Определение shell функции оболочки я описывал ранее, когда говорил о Грамматике shell, они сохраняют серию команд для последующего выполнения. Когда имя команды shell функции используется в качестве простого имени команды, список команд, связанных с этим именем функций выполняется. Функции выполняются в контексте текущей оболочки, для их интерпритации не создается новый процесс(это наподобие выполнения shell скрипта). Когда выполняется функция, аргументы функции становятся позиционными параметрами в ходе выполнения. Специальный параметр «#» обновляется в соответствии с изменениями. Специальный параметр «0» остается неизменным. Имя функции, которая выполняется, запоминается в переменной FUNCNAME.

Все иные аспекты командного интерпретатора shell, идентичны функциям вызывающимся со следующими исключениями: DEBUG и RETURN traps не наследуется функция unless с заданным атрибутом trace, или включена shell опция -o functrace с помошью встроенной команды set, и ERR trap не наследуется если shell опция -o errtrace включена.

Локальные переменные функции могут быть объявлены с локальной встроенной командой. Как правило переменные и их значения разделяются на функции и её абонента.

Переменная FUNCNEST если установлена в числовое значение больше 0, определяет максимальный уровень вложенности функций. Вызовы функций, которые превышают лимит вложенности, приводит всю команду к прерыванию.

Если встроенная команда return выполняется внутри функции, функции прекращаются и возобновляются со следующей команды после вызова функции. Любая команда связанная с RETURN trap выполняется до выполнения возобновления. Когда функция завершается, значение позиционных параметров и специального параметра «#» становятся равными значениям, которые были до выполнения функции.

Имена функций и определения могут быть перечислены с опцией -f встроенных команд declare или typeset. declare или typeset с опцией -F перечислит только имена функций(и возможно, исходного файла и номер строки, если включен FUNCNEST а shell опция extdebug). Функции могут экспортироваться так, чтобы подоболочки автоматически имели их определения со встроенной командой export с опцией -f. Определение функции может быть удалено с помощью встроенной команды unset с опцией -f. Обратите внимание что shell функции и переменные с таким же именем могут привести к нескольким одинаковым именам записей в окружающую среду передающейся порожденным shell оболочкам. Следует проявлять осторожность в случаях когда это может привести к проблеме.

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

Псевдонимы в bash

Псевдонимы в bash позволяют заменить строку на одно слово, когда псевдоним используется в качестве первого слова простой команды. Shell поддерживает список псевдонимов которые можно включать и отключать с помощью встроенных команд alias и unalias. Первое слово каждой простой команды, если оно без кавычек, проверяется, чтобы увидеть имеет ли оно псевдоним. Если слово псевдоним имеет, то оно заменяется текстом псевдонима. В псевдониме не может быть символов «/», «$», «`», и «=», а так же метасимволов или символов заключенных в кавычки. Заменяемый текст, может содержать любые допустимые ко вводу в shell символы в том числе метасимволы. Первое слово заменяемого текста проверяется на псевдонимы, но слово идентичное расширяемому псевдониму не расширяется второй раз. Это значит что может быть один псевдоним, например ls расширяемый ls -F, и bash не пытается рекурсивно расширять замененный текст. Если последний символ значения псевдонима пуст, то следующее слово команды, после псевдонима, также проверяется для расширения псевдонима.

Псевдонимы создаются при помощи команды alias, и удаляются при помощи команды unalias.

Не существует механизма для использования аргументов в заменяемом тексте. Если же аргумент необходим, должны быть использованны функции shell.

Псевдонимы не расширяются когда shell не является интерактивным, shell опция expand_aliases должна быть включена, это делается с использованием shopt.

shopt -s expand_aliases

Здесь «shopt» команда оболочки которая управляет опциями, «-s» разрешает опцию, а «expand_aliases» является необходимой нам опцией.

Правила касающиеся определения и использования псевдонимов несколько запутаны. Bash всегда читает по крайней мере одну полную введенную строку, прежде чем выполнять любые команды этой строки. Псевдонимы расширяются при чтении команды, но не при её выполнении. Таким образом, определение псевдонима, появляется в той же строке, иная команда в этой строке не вступает в силу до следующего ввода чтения строки. Команды следующие за определением псевдонима в строке, не влияют на новый псевдоним.. Это поведение тоже является проблемой когда выполняются функции. Псевдонимы расширяются когда функция определяется для чтения, а не тогда, когда она непосредственно выполняется, так как определение функции само по себе является составной командой. Чтобы обезопасить себя, всегда ставьте определения псевдонимов в отдельной строке, и не используйте псевдонимы в составных командах.

Для большинства целей, псевдонимы заменяются shell функциями.