script parameter functions def bash function return-value

parameter - Valor de retorno en una función Bash



def function bash (9)

Estoy trabajando con un script de bash y quiero ejecutar una función para imprimir un valor de retorno:

function fun1(){ return 34 } function fun2(){ local res=$(fun1) echo $res }

Cuando ejecuto fun2 , no se imprime "34". ¿Por qué es este el caso?


Aunque bash tiene una declaración de return , lo único que puede especificar es el estado de exit propio de la función (un valor entre 0 y 255 , 0 significa "éxito"). Así que el return no es lo que quieres.

Es posible que desee convertir su declaración de return en una declaración de echo ; de esa manera, la salida de su función podría capturarse utilizando llaves $() , que parece ser exactamente lo que desea.

Aquí hay un ejemplo:

function fun1(){ echo 34 } function fun2(){ local res=$(fun1) echo $res }

Otra forma de obtener el valor de retorno (si solo desea devolver un número entero de 0-255) es $? .

function fun1(){ return 34 } function fun2(){ fun1 local res=$? echo $res }

Además, tenga en cuenta que puede usar el valor de retorno para usar la lógica booleana como fun1 || fun2 fun1 || fun2 solo ejecutará fun2 si fun1 devuelve un valor de 0 . El valor de retorno predeterminado es el valor de salida de la última instrucción ejecutada dentro de la función.


Como un complemento a las excelentes publicaciones de otros, aquí hay un artículo que resume estas técnicas:

  • establecer una variable global
  • establece una variable global, cuyo nombre pasaste a la función
  • configurar el código de retorno (y recogerlo con $?)
  • ''echo'' algunos datos (y recójalos con MYVAR = $ (mi función))

Devolviendo valores de las funciones de Bash


El problema con otras respuestas es que usan un global, que puede sobrescribirse cuando varias funciones están en una cadena de llamadas, o eco, lo que significa que su función no puede generar información de diagnóstico (olvidará que su función hace esto y el "resultado", es decir, el valor de retorno, contendrá más información de la que espera el autor de la llamada, lo que provocará un error extraño), o eval, que es demasiado pesado e intrépido.

La forma correcta de hacer esto es poner las cosas de nivel superior en una función y usar una regla local de alcance dinámico de bash. Ejemplo:

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

Esto produce

nothing hi bye

¡El alcance dinámico significa que ret_val apunta a un objeto diferente dependiendo de la persona que llama! Esto es diferente del alcance léxico, que es el que utilizan la mayoría de los lenguajes de programación. Esta es en realidad una característica documentada , simplemente fácil de perder, y no muy bien explicada, aquí está la documentación (el énfasis es mío):

Las variables locales a la función se pueden declarar con la función interna local. Estas variables son visibles solo para la función y los comandos que invoca .

Para alguien con un fondo C / C ++ / Python / Java / C # / javascript, este es probablemente el mayor obstáculo: las funciones en bash no son funciones, son comandos y se comportan como tales: pueden salir a stdout / stderr, pueden Tubo de entrada / salida, pueden devolver un código de salida. Básicamente, no hay diferencia entre definir un comando en una secuencia de comandos y crear un archivo ejecutable al que se puede llamar desde el comando.

Así que en lugar de escribir tu guión de esta manera:

top-level code bunch of functions more top-level code

escríbelo así:

# define your main, containing all top-level code main() bunch of functions # call main main

donde main () declara ret_val como local y todas las demás funciones devuelven valores a través de ret_val.

Consulte también https://unix.stackexchange.com/questions/282557/scope-of-local-variables-in-shell-functions .


La declaración de return establece el código de salida de la función, lo mismo que la exit para todo el script.

El código de salida para el último comando siempre está disponible en $? variable.

function fun1(){ return 34 } function fun2(){ local res=$(fun1) echo $? # <-- Always echos 0 since the ''local'' command passes. res=$(fun1) echo $? #<-- Outputs 34 }


Las funciones en Bash no son funciones como en otro lenguaje; En realidad son comandos. Por lo tanto, las funciones se utilizan como si fueran archivos binarios o scripts recuperados de su ruta. Desde la perspectiva de la lógica de tu programa, realmente no debería haber diferencia.

Los comandos de shell están conectados por canalizaciones (también conocidas como secuencias), y no por tipos de datos fundamentales o definidos por el usuario, como en los lenguajes de programación "reales". No existe tal cosa como un valor de retorno para un comando, tal vez principalmente porque no hay una forma real de declararlo. Podría ocurrir en la página del manual o en la salida --help del comando, pero ambas son solo legibles por humanos y, por lo tanto, están escritas al viento.

Cuando un comando desea obtener una entrada, la lee de su flujo de entrada o de la lista de argumentos. En ambos casos, las cadenas de texto tienen que ser analizadas.

Cuando un comando quiere devolver algo, debe echo a su flujo de salida. Otra forma a menudo practicada es almacenar el valor de retorno en variables globales dedicadas. Escribir en el flujo de salida es más claro y más flexible, ya que también puede tomar datos binarios. Por ejemplo, puede devolver un BLOB fácilmente:

encrypt() { gpg -c -o- $1 # encrypt data in filename to stdout (asks for a passphrase) } encrypt public.dat > private.dat # write function result to file

Como otros han escrito en este hilo, la persona que llama también puede usar el comando de sustitución $() para capturar la salida.

Paralelamente, la función "devolvería" el código de salida de gpg (GnuPG). Piense en el código de salida como un bono que otros idiomas no tienen, o, dependiendo de su temperamento, como un "Schmutzeffekt" de funciones de shell. Este estado es, por convención, 0 en caso de éxito o un número entero en el rango 1-255 para otra cosa. Para dejar esto en claro: return (como exit ) solo puede tomar un valor de 0-255, y los valores distintos de 0 no son necesariamente errores, como se suele afirmar.

Cuando no proporciona un valor explícito con return el estado se toma del último comando en una declaración / función / comando Bash y así sucesivamente. Así que siempre hay un estado, y el return es solo una forma fácil de proporcionarlo.


Me gusta hacer lo siguiente si se ejecuta en un script donde se define la función:

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"

Me gusta esto, porque entonces puedo incluir sentencias de eco en mis funciones si quiero

my_function() { echo "-> my_function()" # do stuff POINTER="my_function_return" echo "<- my_function. $POINTER" }


Otra forma de lograr esto es mediante referencias de nombre (requiere Bash 4.3+).

function example { local -n VAR=$1 VAR=foo } example RESULT echo $RESULT


$(...) captura el texto enviado a stdout por el comando contenido en. return no sale a la salida estándar. $? Contiene el código de resultado del último comando.

fun1 (){ return 34 } fun2 (){ fun1 local res=$? echo $res }


Git Bash en Windows usando matrices para múltiples valores de retorno

CÓDIGO DE 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 ##$1 and $2 some sensible names: local out_dex_1="$1" ##output index local out_dex_2="$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:"

RENDIMIENTO ESPERADO:

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: