function function_name { command... }
или
function_name () { command... }
Вторая форма записи ближе к сердцу C-программистам (она же более переносимая).
Как и в языке C, скобка, открывающая тело функции, может помещаться на следующей строке.
function_name () { command... }
Вызов функции осуществляется простым указанием ее имени в тексте сценария.
Пример 22-1. Простая функция
#!/bin/bash
funky ()
{
echo "Это обычная функция."
} # Функция должна быть объявлена раньше, чем ее можно будет использовать.
# Вызов функции.
funky
exit 0
Функция должна быть объявлена раньше, чем ее можно будет использовать. К сожалению, в Bash нет возможности "опережающего объявления" функции, как например в C.
f1
# Эта строка вызовет сообщение об ошибке, поскольку функция "f1" еще не определена.
declare -f f1 # Это не поможет.
f1 # По прежнему -- сообщение об ошибке.
# Однако...
f1 ()
{
echo "Вызов функции \"f2\" из функции \"f1\"."
f2
}
f2 ()
{
echo "Функция \"f2\"."
}
f1 # Функция "f2", фактически, не вызывается выше этой строки,
#+ хотя ссылка на нее встречается выше, до ее объявления.
# Это допускается.
# Спасибо S.C.
Допускается даже создание вложенных функций, хотя пользы от этого немного.
f1 ()
{
f2 () # вложенная
{
echo "Функция \"f2\", вложенная в \"f1\"."
}
}
f2 # Вызывает сообщение об ошибке.
# Даже "declare -f f2" не поможет.
echo
f1 # Ничего не происходит, простой вызов "f1", не означает автоматический вызов "f2".
f2 # Теперь все нормально, вызов "f2" не приводит к появлению ошибки,
#+ поскольку функция "f2" была определена в процессе вызова "f1".
# Спасибо S.C.
Объявление функции может размещаться в самых неожиданных местах.
ls -l | foo() { echo "foo"; } # Допустимо, но бесполезно.
if [ "$USER" = bozo ]
then
bozo_greet () # Объявление функции размещено в условном операторе.
{
echo "Привет, Bozo!"
}
fi
bozo_greet # Работает только у пользователя bozo, другие получат сообщение об ошибке.
# Нечто подобное можно использовать с определеной пользой для себя.
NO_EXIT=1 # Will enable function definition below.
[[ $NO_EXIT -eq 1 ]] && exit() { true; } # Определение функции в последовательности "И-список".
# Если $NO_EXIT равна 1, то объявляется "exit ()".
# Тем самым, функция "exit" подменяет встроенную команду "exit".
exit # Вызывается функция "exit ()", а не встроенная команда "exit".
# Спасибо S.C.
22.1. Сложные функции и сложности с функциями
Функции могут принимать входные аргументы и возвращать код завершения.
function_name $arg1 $arg2
Доступ к входным аргументам, в функциях, производится посредством позиционных параметров, т.е. $1, $2 и так далее.
Пример 22-2. Функция с аргументами
#!/bin/bash
# Функции и аргументы
DEFAULT=default # Значение аргумента по-умолчанию.
func2 () {
if [ -z "$1" ] # Длина аргумента #1 равна нулю?
then
echo "-Аргумент #1 имеет нулевую длину.-" # Или аргумент не был передан функции.
else
echo "-Аргумент #1: \"$1\".-"
fi
variable=${1-$DEFAULT} # Что делает
echo "variable = $variable" #+ показанная подстановка параметра?
# ---------------------------
# Она различает отсутствующий аргумент
#+ от "пустого" аргумента.
if [ "$2" ]
then
echo "-Аргумент #2: \"$2\".-"
fi
return 0
}
echo
echo "Вызов функции без аргументов."
func2
echo
echo "Вызов функции с \"пустым\" аргументом."
func2 ""
echo
echo "Вызов функции с неинициализированным аргументом."
func2 "$uninitialized_param"
echo
echo "Вызов функции с одним аргументом."
func2 first
echo
echo "Вызов функции с двумя аргументами."
func2 first second
echo
echo "Вызов функции с аргументами \"\" \"second\"."
func2 "" second # Первый параметр "пустой"
echo # и второй параметр -- ASCII-строка.
exit 0
Команда shift вполне применима и к аргументам функций (см. Пример 33-10).
В отличие от других языков программирования, в сценариях на языке командной оболочке, в функции передаются аргументы по значению[ 50 ]. Если имена переменных (которые фактически являются указателями) передаются функции в виде аргументов, то они интерпретируются как обычные строки символов и не могут быть разыменованы. Функции интерпретируют свои аргументы буквально.
50
Механизм косвенных ссылок на переменные (см. Пример 34-2) слишком неудобен для передачи аргументов по ссылке.