Функция Bash — это, по сути, набор команд, который можно вызывать множество раз. Цель функции — помочь вам сделать ваши сценарии bash более читаемыми и избежать написания одного и того же кода.
По сравнению с большинством языков программирования, функции Bash сильно ограничены. В этом руководстве мы рассмотрим основы функций Bash и разберемся, как использовать их в скриптах оболочки shell.
Объявление функции Bash
Синтаксис объявления очень прост и похож на многие популярные языки программирования. Есть два основных формата объявления:
- Формат может начинаться с имени функции, за которым следуют круглые скобки. Это предпочтительный и наиболее популярный формат.
function_name () { commands }
Этот же код можно написать в одну строку:
function_name () { commands; }
- Второй формат начинается с зарезервированного слова function, за которым следует имя функции.
function function_name { commands }
Версия в одну строку:
function function_name { commands; }
Несколько моментов, которые следует запомнить:
- Список команд, находящихся между фигурными скобками {} — это тело функции. Фигурные скобки, окружающие тело функции, должны быть отделены от тела пробелами или начинаться с новой строки.
- Простое определение функции не выполняет её. Чтобы вызвать функцию bash, просто используйте имя созданной функции. Команды между фигурными скобками выполнятся, когда функция вызывается через shell оболочку.
- Соблюдайте порядок написания кода. Определение функции должно быть перед её вызовом.
- При использовании одно-строчных функций необходимо установить точку с запятой у последней команды.
- Старайтесь давать имена, которые описывают процесс происходящий внутри тела функции. Чтобы в будущем понимать что делает программный код, взглянув лишь на название.
Чтобы лучше понять базовые правила, взглянем на следующий пример:
#!/bin/bash hello_world () { echo 'привет, мир' } hello_world
Проанализируем написанный код:
- В третьей мы определяем функцию с именем hello_world и открывая фигурную скобку {, которая отмечает начало тела функции.
- Строка 4 — это тело функции. Обычно, тело занимает более одной строки.
- В пятой строке стоит закрывающая фигурная скобка }. Она определяет конец функции.
- В строке 7 мы выполняем созданную функцию. Выполнять ее можно столько раз, сколько вам нужно.
Если запустить такой скрипт в консоли, он выведет на экран строку:
привет, мир
Область переменных
Глобальные переменные — это переменные, к которым можно получить доступ из любой точки скрипта независимо от области их объявления. В Bash все переменные по умолчанию определяются как глобальные, даже если они объявлены внутри одной функции.
Локальные переменные могут быть объявлены в теле функции с ключевым словом local, а использоваться могут только внутри неё. Вы можете иметь локальные переменные с одинаковым именем в разных функциях. Чтобы лучше понять, как работает область переменных в Bash, рассмотрим пример:
#!/bin/bash var1='A' var2='B' my_function () { local var1='C' var2='D' echo "Внутри функции: var1: $var1, var2: $var2" } echo "Перед запуском: var1: $var1, var2: $var2" my_function echo "После запуска: var1: $var1, var2: $var2"
Этот скрипт начинается с определения двух глобальных переменных var1 и var2. Затем объявление функции, которая присваивает локальной переменной var1 и изменяет глобальную переменную var2.
Если вы запустите сценарий, вы увидите следующие строки:
Перед запуском: var1: A, var2: B Внутри функции: var1: C, var2: D После запуска: var1: A, var2: D
Из этого следует простой вывод:
- Если вы задаёте локальную переменную внутри тела функции с тем же именем, что и существующая глобальная, локальная будет иметь приоритет над глобальной.
- Глобальные переменные могут быть изменены внутри функции.
Возвращаем значения
В отличие от функций на “реальных” языках программирования, функции в Bash не позволяют возвращать значение при вызове. Когда функция bash завершается, ее возвращаемое значение — это значение последнего оператора: 0 — успех, а ненулевое десятичное число в диапазоне от 1 до 255 включительно — для описания сбоя.
Статус возврата значения можно указать с помощью ключевого слова return и оно присваивается переменной $?. Оператор return завершает работу функции. Вы можете думать об этом как о способе выхода из функции.
#!/bin/bash my_function () { echo "наш результат" return 13 } my_function echo $?
Вывод консоли: наш результат 13
Как же, все-таки, вернуть значение из функции? Нам нужно использовать для этого небольшую хитрость — можно присвоить результат функции глобальной переменной:
#!/bin/bash my_function () { func_result="наш результат" } my_function echo $func_result
После выполнения этого кода, вы должны увидеть строку на экране:
наш результат
Другой, подходящий вариант для возврата значения из функции — отправить значение в stdout с помощью echo или printf, как показано ниже:
#!/bin/bash my_function () { local func_result="это тест" echo "$func_result" } func_result="$(my_function)" echo $func_result
Результат выполнения будет таким же.
Вместо того, чтобы просто выполнять функцию, которая будет печатать сообщение в stdout, мы присваиваем результат переменной func_result с помощью механизма $ (). Используя этот метод, глобальная переменная func_result будет содержать результат функции.
Передача аргументов
Чтобы передать любое количество аргументов функции bash, просто поместите их сразу после имени функции, разделяя каждую пробелом. Соблюдайте основные рекомендации при передаче параметров:
- Переданные параметры $1, $2, $3 … $n, соответствуют номеру параметра по порядку, заданными после имени функции.
- Переменная $0 зарезервирована для имени функции.
- Переменная $# содержит общее количество аргументов, переданных функции.
- Переменная $* или $@ содержит все параметры, переданные функции.
Пример передачи аргументов:
#!/bin/bash greeting () { echo "Привет, $1" } greeting "Алиса"
Результатом выполнения этого кода будет строка:
Привет, Алиса
Теперь у вас есть некоторые знания для того, чтобы правильно писать функции bash.
Примеры
Функция таймер, которая считает сколько прошло времени:
timer() { local t; t=$(date '+%s'); test $# -gt 0 && let t-=$1; echo "$t"; } ... t=$(timer) ... ... t=$(timer $t) echo "time used = $t secs"