9 ответов:
хотя Баш имеет
returnоператор, единственное, что вы можете указать с его помощью-это собственная функцияexitстатус (значение между0и255, 0 означает "успех"). Так чтоreturnне то, что вы хотите.вы можете конвертировать ваш
returnзаявление кechoоператор-таким образом, ваш вывод функции может быть захвачен с помощью$()фигурные скобки, которые, кажется, именно то, что вы хотите.вот это пример:
function fun1(){ echo 34 } function fun2(){ local res=$(fun1) echo $res }другой способ, чтобы получить возвращаемое значение (если вы просто хотите вернуть целое число 0-255) составляет
$?.function fun1(){ return 34 } function fun2(){ fun1 local res=$? echo $res }кроме того, обратите внимание, что вы можете использовать возвращаемое значение, чтобы использовать булеву логику, как
fun1 || fun2толькоfun2еслиfun1возвращает a0значение. Возвращаемое значение по умолчанию-это выходное значение последнего оператора, выполненного в функции.
$(...)захватывает текст, отправленный в stdout командой, содержащейся внутри.returnне выводится в stdout.$?содержит код результата выполнения последней команды.fun1 (){ return 34 } fun2 (){ fun1 local res=$? echo $res }
функции в Bash не являются функциями, как на другом языке; они на самом деле команды. Таким образом, функции используются так, как если бы они были двоичными файлами или скриптами, извлеченными из вашего пути. С точки зрения логики вашей программы не должно быть никакой разницы.
команды оболочки соединены трубами (aka streams), а не фундаментальными или пользовательскими типами данных, как в "реальных" языках программирования. Нет такой вещи, как возвращаемое значение для команды, может быть, в основном потому, что нет никакого реального способа заявить об этом. Это может произойти на man-странице, или
--helpвывод команды, но оба они только читаются человеком и, следовательно, записываются на ветер.когда команда хочет получить ввод, она считывает его из своего входного потока или списка аргументов. В обоих случаях текстовые строки должны быть проанализированы.
когда команда хочет что-то вернуть, она должна
echoэто к его выходному потоку. Другим часто практикуемым способом является сохранение возвращаемого значения в выделенные, глобальные переменные. Запись в выходной поток более четкая и гибкая, потому что она может принимать также двоичные данные. Например, вы можете легко вернуть большой двоичный объект:encrypt() { gpg -c -o- # encrypt data in filename to stdout (asks for a passphrase) } encrypt public.dat > private.dat # write function result to fileкак другие написали в этом потоке, вызывающий также может использовать подстановку команд
$()для вывода данных.параллельно, функция будет возвращать код выхода
gpg(GnuPG). Подумайте о коде выхода как о бонусе, которого нет в других языках, или, в зависимости от вашего темперамент, как "Шмутцэффект" функций оболочки. Этот статус, по соглашению, 0 на успех или целое число в диапазоне 1-255 для чего-то еще. Чтобы было понятно:return(какexit) может принимать только значение от 0-255, а значения, отличные от 0, не обязательно являются ошибками, как это часто утверждается.когда вы не предоставляете явное значение с
returnстатус берется из последней команды в операторе/функции/команде Bash и так далее. Так что всегда есть статус, иreturnэто просто простой способ обеспечить его.
The
returnоператор устанавливает код выхода функции, почти такой же, какexitбудет делать для всего скрипта.код выхода для последней команды всегда доступен в
$?переменной.function fun1(){ return 34 } function fun2(){ local res=$(fun1) echo $? # <-- Always echos 0 since the 'local' command passes. res=$(fun1) echo $? #<-- Outputs 34 }
Я хотел бы сделать следующее, если работает в скрипте, где функция определена:
POINTER= # used for function return values my_function() { # do stuff POINTER="my_function_return" } my_other_function() { # do stuff POINTER="my_other_function_return" } my_function RESULT="$POINTER" my_other_function RESULT="$POINTER"мне это нравится, потому что я могу включить эхо-операторы в мои функции, если я хочу
my_function() { echo "-> my_function()" # do stuff POINTER="my_function_return" echo "<- my_function. $POINTER" }
в качестве дополнения к отличным сообщениям других, вот статья, обобщающая эти методы:
- установить глобальную переменную
- установите глобальную переменную, имя которой вы передали функции
- установить код возврата (и забрать его с $?)
- 'echo' некоторые данные (и забрать его с MYVAR=$(myfunction))
проблема с другими ответами заключается в том, что они либо используют глобальный, который может быть перезаписан, когда несколько функций находятся в цепочке вызовов, либо echo, что означает, что ваша функция не может выводить диагностическую информацию (вы забудете, что ваша функция делает это, и "результат", т. е. возвращаемое значение, будет содержать больше информации, чем ожидает ваш вызывающий, что приводит к странной ошибке), или eval, который является тяжелым и хакерским.
правильный способ сделать это-поместить материал верхнего уровня в функцию и использовать локальный с помощью правило динамического обзора Баша. Пример:
func1() { ret_val=hi } func2() { ret_val=bye } func3() { local ret_val=nothing echo $ret_val func1 echo $ret_val func2 echo $ret_val } func3выводит
nothing hi byeдинамическая область означает, что ret_val указывает на другой объект в зависимости от вызывающего абонента! Это отличается от лексической области, которая используется в большинстве языков программирования. Это на самом деле документированные функции, просто легко пропустить, и не очень хорошо объяснил, Вот документы для него (акцент мой):
локальные переменные функции могут быть объявленный с местным встроенный. Эти переменные видны только функции и команды, которые он вызывает.
для кого-то с фоном C/C++/Python/Java/C#/javascript это, вероятно, самое большое препятствие: функции в bash не являются функциями, они являются командами и ведут себя так: они могут выводить в stdout/stderr, они могут вводить/выводить, они могут возвращать код выхода. В принципе нет никакой разницы между определением команда в скрипте и создание исполняемого файла, который может быть вызван из команды.
поэтому вместо того, чтобы писать свой сценарий так:
top-level code bunch of functions more top-level codeнаписать так:
# define your main, containing all top-level code main() bunch of functions # call main mainгде main () объявляет ret_val локальным, а все остальные функции возвращают значения через ret_val.
Смотрите также https://unix.stackexchange.com/questions/282557/scope-of-local-variables-in-shell-functions.
еще один способ достичь этого -название ссылки (требуется Bash 4.3+).
function example { local -n VAR= VAR=foo } example RESULT echo $RESULT
Git Bash on Windows использование массивов для несколько возвращаемые значения
BASH КОД:
#!/bin/bash ##A 6-element array used for returning ##values from functions: declare -a RET_ARR RET_ARR[0]="A" RET_ARR[1]="B" RET_ARR[2]="C" RET_ARR[3]="D" RET_ARR[4]="E" RET_ARR[5]="F" function FN_MULTIPLE_RETURN_VALUES(){ ##give the positional arguments/inputs ## and some sensible names: local out_dex_1="" ##output index local out_dex_2="" ##output index ##Echo for debugging: echo "running: FN_MULTIPLE_RETURN_VALUES" ##Here: Calculate output values: local op_var_1="Hello" local op_var_2="World" ##set the return values: RET_ARR[ $out_dex_1 ]=$op_var_1 RET_ARR[ $out_dex_2 ]=$op_var_2 } echo "FN_MULTIPLE_RETURN_VALUES EXAMPLES:" echo "-------------------------------------------" fn="FN_MULTIPLE_RETURN_VALUES" out_dex_a=0 out_dex_b=1 eval $fn $out_dex_a $out_dex_b ##<--Call function a=${RET_ARR[0]} && echo "RET_ARR[0]: $a " b=${RET_ARR[1]} && echo "RET_ARR[1]: $b " echo ##----------------------------------------------## c="2" d="3" FN_MULTIPLE_RETURN_VALUES $c $d ##<--Call function c_res=${RET_ARR[2]} && echo "RET_ARR[2]: $c_res " d_res=${RET_ARR[3]} && echo "RET_ARR[3]: $d_res " echo ##----------------------------------------------## FN_MULTIPLE_RETURN_VALUES 4 5 ##<---Call function e=${RET_ARR[4]} && echo "RET_ARR[4]: $e " f=${RET_ARR[5]} && echo "RET_ARR[5]: $f " echo ##----------------------------------------------## read -p "Press Enter To Exit:"ОЖИДАЕМЫЙ РЕЗУЛЬТАТ:
FN_MULTIPLE_RETURN_VALUES EXAMPLES: ------------------------------------------- running: FN_MULTIPLE_RETURN_VALUES RET_ARR[0]: Hello RET_ARR[1]: World running: FN_MULTIPLE_RETURN_VALUES RET_ARR[2]: Hello RET_ARR[3]: World running: FN_MULTIPLE_RETURN_VALUES RET_ARR[4]: Hello RET_ARR[5]: World Press Enter To Exit:
Comments