Возврат значений из функций Bash

Returning Values from Bash Functions
Sep 11, 2009 By Mitch Frazier
in HOW-TOs
http://www.linuxjournal.com/content/return-values-bash-functions

Функции Bash, в отличие от функций в большинстве языков программирования, не предоставляют прозрачной возможности вернуть результат выполнения. Когда Bash-функция завершается, она возвращает статус этого завершения: нуль для успешного завершения, не-нуль - для сигнализации о проблемах. Для возврата значений можно задать глобальную переменную для забора в нее значения, или использовать подстановку, или передать значение в локальную переменную. Примеры ниже показывают, как использовать эти подходы.

Хотя Bash возвращает код завершения, какое это имеет практическое значение? что с ним делать? Код возврата содержится в переменной $? . Если функция по каким-либо причинам не возвращает код завершения, этим кодом будет служить код возврата последней инструкции внутри функции. Поэтому нужны ухищрения.

Простейший путь - задать глобальную переменную для хранения результата. Поскольку по умолчанию в Bash все переменные глобальные, это просто:

function myfunc()
{
myresult='some value'
}

myfunc
echo $myresult

Этот код устанавливает глобальную переменную myresult внутри функции result. Довольно просто, но, как всем нам хорошо известно, установка глобальных переменных в больших программах может привести к появлению трудноотлавливаемых багов.

Лучшей практикой будем считать использование локальных переменных. Основной проблемой, которую нужно преодолеть, это как вернуть значение вызывающему функцию процессу. Один из способов - использовать командную подстановку:

function myfunc()
{
local myresult='some value'
echo "$myresult"
}

result=$(myfunc) # or result=`myfunc`
echo $result

Здесь result появится в потоке стандартного вывода и появляется возможность захватить его с помощью подстановки. Дальше переменная может быть использована при необходимости.

Другой путь возвратить значение - передать в функцию имя переменной в качестве одного из параметров командной строки и в нее записать результат выполнения функции:

function myfunc()
{
local __resultvar=$1
local myresult='some value'
eval $__resultvar="'$myresult'"
}

myfunc result
echo $result

Поскольку мы имеем некое имя переменной, в которой храним имя переменной с результатом, мы можем задать возвращаемую переменную непосредственно в командной строке. Здесь необходимо использовать eval для присвоения значения.

Когда мы храним имя переменной, переданное из командной строки, следует быть уверенным, что именно это имя не будет использовано вызывающим процессом (поэтому я на всякий случай использую здесь __resultvar, а не resultvar). Если это все-таки произойдет, переменная результата не будет задана. К примеру, нижеследующая конструкция работать не будет:

function myfunc()
{
local result=$1
local myresult='some value'
eval $result="'$myresult'"
}

myfunc result
echo $result

Причина, по которой это не работает, заключается в особенностях инструкции eval. Когда eval выполняет вторую интерпретацию и вычисляет result='some value', result с этого момента - локальная переменная и не выйдет за пределы функции.

Для большей универсальности вы можете сочетать оба способа, и передачу имени в параметре, и подстановку:

function myfunc()
{
local __resultvar=$1
local myresult='some value'
if [[ "$__resultvar" ]]; then
eval $__resultvar="'$myresult'"
else
echo "$myresult"
fi
}

myfunc result
echo $result
result2=$(myfunc)
echo $result2

Если имя не было передано в параметре, возвращаемое значение будет выдано на станартный вывод.

______________________



Назад в тематический каталог