Перейти к главному содержимому

Функции в bash

Задать функцию

Функции в bash можно задавать двумя способами:

# Способ 1
function_name () {
  commands
}

# Способ 2
function function_name {
  commands
}

Простые функции можно объявлять в одну строку. При этом пробелы между фигурными скобками и телом функции важны!. И последним в теле должен быть ; (точка с запятой).

Объявление функций в одну строку:

# Способ 1
function_name () { commands; }

# Способ 2
function function_name { commands; }

Итого по объявлению функций:

  • Тело функций (всё что между фигурными скобками) должно отделяться от самих фигурных скобок переносом строки или пробелами;
  • Определение функции не вызывает её (как и в нормальных языках);
  • Определение функции должно быть выше чем её вызовы;
  • Тело однострочных функций должно заканчиваться ; (точкой с запятой).

Переменные

Глобальные переменные видны в функциях и могут быть модифицированы в функциях. Локальные переменные (область видимости внутри функции) должны объявляться с ключевым словом local.

Локальные переменные имеют приоритет над глобальными если используется одно и то же имя.

#!/bin/bash

var1='A'
var2='B'

my_function () {
  local var1='C'
  var2='D'
  echo "Inside function: var1: $var1, var2: $var2"
}

echo "Before executing function: var1: $var1, var2: $var2"

my_function

echo "After executing function: var1: $var1, var2: $var2"

Вывод этого скрипта:

Before executing function: var1: A, var2: B
Inside function: var1: C, var2: D
After executing function: var1: A, var2: D

Параметры

Чтобы передать параметры в функцию надо просто написать их после вызова, разделяя пробелами. Имеет смысл заключать их в кавычки, тогда можно передавать параметры с пробелами.

  • Внутри функции доступ к параметрам осуществляется через переменные $1, $2, $3 и т.д.
  • Переменная $0 содержит имя самой функции.
  • Переменная $# содержит количество переданных параметров.
  • Переменные $* и $@ содержать все парамеры, переданные функцию.

Отличия переменных $* и $@

  • Если эти переменные НЕ заключать в кавычки, то они эквивалентны;
  • В кавычках "$*" раскрывается в одну строку "$1 $2 ... $n";
  • В кавычках "$@" раскрывается в разные строки "$1" "$2" ... "$n".

Пример:

#!/bin/bash

greeting () {
  echo "Hello $1"
}

greeting "World"

Возвращаемые значения

В отличие от функций в "настоящих" языках программирования, функции в Bash не позволяют возвращать значения как это принято. Когда функция bash заканчивает выполнение, ее возвращаемое значение это статус последней выполненной команды в теле функции, обычно 0 при успешном завершении, число 1-255 код ошибки.

Это число можно указать явно при использовании команды return, после чего оно будет сохранено в специальной переменной $?. Команда return прерывает выполнение функции (как и в обычных языках), а код ошибки можно рассматривать как статус выполнения.

Пример:

#!/bin/bash

my_function () {
  echo "some result"
  return 55
}

my_function
echo $?

Вывод этого скрипта:

some result
55

Чтобы по-настоящему что-то вернуть из функции надо использовать что-то другое. Самый простой вариант - присвоить что-то глобальной переменной:

#!/bin/bash

my_function () {
  func_result="some result"
}

my_function
echo $func_result

Вывод этого скрипта:

some result

Есть способ получше. Отправить требуемое возвращаемое значение на вывод (при помощи echo или printf, например):

#!/bin/bash

my_function () {
  local func_result="some result"
  echo "$func_result"
}

func_result="$(my_function)"
echo $func_result

Вывод этого скрипта:

some result

Тут вместо простого вызова (который просто напечатает строку) вызов функции "оборачивается" в оператор $(...), после чего переменная будет содержать то, что функция "хотела" напечатать.

Переопределение команд

Можно сделать функцию с именем, таким же как существующая команда. В этом случае, вместо команды будет вызываться функция. так можно добавлять, например, дополнительные опции во все вызовы команд сразу, или ещё как-то шаманить, чтоб не править много мест в скрипте сразу.

Пример:

#!/bin/bash

#overriding command
echo(){
    builtin echo "The name is : $1"
}

echo "Edward III"

Вывод этого скрипта:

The name is : Edward III