Искусство программирования на языке сценариев командной оболочки
Шрифт:
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 "Вызов
func2 "" second # Первый параметр "пустой"
echo # и второй параметр -- ASCII-строка.
exit 0
50
Механизм косвенных ссылок на переменные (см. Пример 34-2) слишком неудобен для передачи аргументов по ссылке.
#!/bin/bash
ITERATIONS=3 # Количество вводимых значений.
icount=1
my_read {
# При вызове my_read varname,
# выводит предыдущее значение в квадратных скобках,
# затем просит ввести новое значение.
local local_var
echo -n "Введите говое значение переменной "
eval 'echo -n "[$'$1'] "' # Прежнее значение.
read local_var
[ -n "$local_var" ] && eval $1=\$local_var
# Последовательность "And-list": если "local_var" не пуста, то ее значение переписывается в "$1".
}
echo
while [ "$icount" -le "$ITERATIONS" ]
do
my_read var
echo "Значение #$icount = $var"
let "icount += 1"
echo
done
# Спасибо Stephane Chazelas за этот поучительный пример.
exit 0
Exit и Return
код завершения
Функции возвращают значение в виде кода завершения. Код завершения может быть задан явно, с помощью команды return, в противном случае будет возвращен код завершения последней команды в функции (0 -- в случае успеха, иначе -- ненулевой код ошибки). Код завершения в сценарии может быть получен через переменную $?.
return
Завершает исполнение функции. Команда return [ 51 ] может иметь необязательный аргумент типа integer, который возвращается в вызывающий сценарий как "код завершения" функции, это значение так же записывается в переменную $?.
51
Команда return -- это встроенная команда Bash.