Функции оболочки
Функции оболочки — это способ группирования команд для последующего выполнения с использованием одного имени для группы. Они выполняются так же, как и «обычная» команда. Когда имя функции оболочки используется как простое имя команды, выполняется список команд, связанных с этим именем функции. Функции оболочки выполняются в текущем контексте оболочки; для их интерпретации не создается новый процесс.
Функции объявляются с помощью такого синтаксиса:
fname () compound-command [ redirections ]
или
function fname [()] compound-command [ redirections ]
Это определяет функцию оболочки с именем fname. Зарезервированное слово function является необязательным. Если зарезервированное слово function указано, круглые скобки являются необязательными. Тело функции — это составная команда compound-command (см. Составные команды). Эта команда обычно представляет собой list, заключённую в фигурные скобки { и }, но может быть любой составной командой, перечисленной выше. Если используется зарезервированное слово function, но круглые скобки не указаны, фигурные скобки рекомендуются. compound-command выполняется всякий раз, когда fname задаётся как имя простой команды. Когда оболочка находится в режиме POSIX (см. Режим POSIX оболочки Bash), fname должно быть допустимым именем оболочки и не может быть таким же, как одно из специальных встроенных команд (см. Специальные встроенные команды). В режиме по умолчанию имя функции может быть любым необрамленным словом оболочки, которое не содержит ‘$’. Все перенаправления (см. Перенаправления), связанные с функцией оболочки, выполняются при выполнении функции. Определение функции может быть удалено с помощью опции -f для встроенной команды unset (см. Встроенные команды оболочки Bourne).
Код выхода определения функции равен нулю, если не произошла синтаксическая ошибка или не существует функция с таким же именем, помеченная как readonly. При выполнении код выхода функции — это код выхода последней команды, выполненной в теле.
Обратите внимание, что по историческим причинам в наиболее распространённом использовании фигурные скобки, которые окружают тело функции, должны быть разделены от тела с помощью blank или новой строки. Это связано с тем, что фигурные скобки являются зарезервированными словами и распознаются как таковые только тогда, когда они разделены пробелами или другим метасимволом оболочки. Кроме того, при использовании фигурных скобок list должен быть завершен точкой с запятой, ‘&’ или новой строкой.
При выполнении функции аргументы функции становятся позиционными параметрами во время её выполнения (см. Позиционные параметры). Специальный параметр ‘#’, который расширяется до числа позиционных параметров, обновляется, отражая изменения. Специальный параметр 0 остается неизменным. Первый элемент переменной FUNCNAME устанавливается в имя функции во время выполнения функции.
Все остальные аспекты среды выполнения оболочки идентичны между функцией и её вызывающим элементом, за исключением этих моментов: ловушки DEBUG и RETURN не наследуются, если функция не получила атрибут trace с помощью встроенной команды declare или опция -o functrace не была включена с помощью встроенной команды set (в этом случае все функции наследуют ловушки DEBUG и RETURN), и ловушка ERR не наследуется, если опция оболочки -o errtrace не была включена. См. Встроенные команды оболочки Bourne для описания встроенной команды trap.
Переменная FUNCNEST, если она установлена в числовое значение больше 0, определяет максимальный уровень вложенности функций. Вызовы функций, превышающие предел, приводят к прерыванию всей команды.
Если встроенная команда return выполняется в функции, функция завершается, и выполнение возобновляется с последующей командой после вызова функции. Любая команда, связанная с ловушкой RETURN, выполняется перед возобновлением выполнения. Когда функция завершается, значения позиционных параметров и специального параметра ‘#’ восстанавливаются до значений, которые у них были до выполнения функции. Если числовой аргумент задан команде return, это и есть код выхода функции; в противном случае код выхода функции — это код выхода последней выполненной команды до return.
Переменные, локальные для функции, могут быть объявлены с помощью встроенной команды local (локальные переменные). Обычно переменные и их значения разделяются между функцией и её вызывающим элементом. Эти переменные видны только функции и командам, которые она вызывает. Это особенно важно, когда функция оболочки вызывает другие функции.
В следующем описании текущий область видимости — это функция, которая выполняется в данный момент. Предыдущие области видимости состоят из вызывающей функции этой функции и так далее, обратно к «глобальной» области видимости, где оболочка не выполняет никакой функции оболочки. Следовательно, локальная переменная в текущем локальном объёме видимости — это переменная, объявленная с помощью встроенных команд local или declare в функции, которая выполняется в данный момент.
Локальные переменные «затеняют» переменные с тем же именем, объявленные в предыдущих областях видимости. Например, локальная переменная, объявленная в функции, скрывает глобальную переменную с тем же именем: ссылки и присваивания относятся к локальной переменной, оставляя глобальную переменную неизменной. Когда функция возвращается, глобальная переменная снова становится видимой.
Оболочка использует динамическое оперирование областью видимости для управления видимостью переменной в функциях. При динамическом оперировании областью видимости видимые переменные и их значения являются результатом последовательности вызовов функций, которые привели к выполнению текущей функции. Значение переменной, которое видит функция, зависит от её значения в её вызывающей функции, если таковая имеется, будь то «глобальная» область видимости или другая функция оболочки. Это также значение, которое «затеняется» объявлением локальной переменной, и значение, которое восстанавливается при возврате функции.
Например, если переменная var объявлена как локальная в функции func1, и func1 вызывает другую функцию func2, ссылки на var изнутри func2 будут ссылаться на локальную переменную var из func1, затенение любой глобальной переменной с именем var.
Следующий скрипт демонстрирует это поведение. При выполнении скрипт отображает
In func2, var = func1 local
func1()
{
local var='func1 local'
func2
}
func2()
{
echo "In func2, var = $var"
}
var=global
func1
Встроенная команда unset также действует, используя ту же динамическую область видимости: если переменная является локальной для текущей области видимости, unset её отменяет; в противном случае отмена будет относиться к переменной, найденной в любой вызывающей области видимости, как описано выше. Если переменная в текущем локальном объёме видимости отменяется, она останется отменённой (появляясь как отменённая) до тех пор, пока она не будет перезадана в этом объёме или пока функция не вернётся. После возврата функции любая экземпляра переменной в предыдущей области видимости станет видимой. Если отмена воздействует на переменную в предыдущей области видимости, любой экземпляр переменной с таким именем, который был затенено, станет видимым (см. ниже, как опция оболочки localvar_unset изменяет это поведение).
Имена и определения функций можно перечислить с помощью опции -f встроенной команды declare (typeset) (см. Встроенные команды Bash). Опция -F для declare или typeset будет перечислять только имена функций (и, необязательно, исходный файл и номер строки, если включена опция оболочки extdebug). Функции могут быть экспортированы, чтобы дочерние процессы оболочки (те, которые создаются при выполнении отдельного вызова оболочки) автоматически имели их определённые с помощью опции -f встроенной команды export (см. Встроенные команды оболочки Bourne).
Функции могут быть рекурсивными. Переменная FUNCNEST может использоваться для ограничения глубины стека вызовов функций и ограничения числа вызовов функций. По умолчанию количество рекурсивных вызовов не ограничено.
Copyright © 2000, 2001, 2002, 2007, 2008 Free Software Foundation, Inc.
Licensed under the GNU Free Documentation License.
https://www.gnu.org/software/bash/manual/html_node/Shell-Functions.html