Estoy trabajando con un script 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 imprime "34". ¿Por qué es este el caso?
bash
function
return-value
mindia
fuente
fuente
return
en su caso es esencialmente el mismoexit code
que el rango de0 - 255
. Useecho
según lo sugerido por @septi. Los códigos de salida se pueden capturar con$?
.function a() { echo 34; }
function b() { while read data; do echo $data ; done ;}
a | b
Respuestas:
Aunque bash tiene una
return
declaración, lo único que puede especificar con ella es elexit
estado propio de la función (un valor entre0
y255
, 0 significa "éxito"). Entoncesreturn
no es lo que quieres.Es posible que desee convertir su
return
declaración en unaecho
declaración, de esa manera la salida de su función podría capturarse usando$()
llaves, que parece ser exactamente lo que desea.Aquí hay un ejemplo:
Otra forma de obtener el valor de retorno (si solo desea devolver un entero 0-255) es
$?
.Además, tenga en cuenta que puede usar el valor de retorno para usar la lógica booleana,
fun1 || fun2
ya que solo se ejecutaráfun2
sifun1
devuelve un0
valor. El valor de retorno predeterminado es el valor de salida de la última instrucción ejecutada dentro de la función.fuente
fun1
y luego el valor de retorno se almacena en$?
. Aunque no recomendaría hacer eso ...$?
?||
construcción, un código de salida de 0 se considera exitoso y, por lo tanto, "verdadero". No cero es error y, por lo tanto, falso. Piensefun1 || fun2
en la abreviatura de "si fun1 devuelve el éxito o fun2 devuelve el éxito" en lugar de un operador en los valores de retorno reales.$(...)
captura el texto enviado a stdout por el comando que contiene.return
no sale a stdout.$?
contiene el código de resultado del último comando.fuente
return
se utiliza para establecer$?
cuál es elexit status
. En el ejemplo anterior,fun1
'sexit status
sería34
. Además, tenga en cuenta que$(...)
también captura stderr además de stdout del comando especificado.Las funciones en Bash no son funciones como en otro idioma; en realidad son comandos. Por lo tanto, las funciones se usan como si fueran binarios o scripts extraídos de su ruta. Desde la perspectiva de la lógica de su programa, realmente no debería haber diferencia.
Los comandos de Shell están conectados por canalizaciones (también conocidos como flujos) y no por tipos de datos fundamentales o definidos por el usuario, como en los lenguajes de programación "reales". No existe 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 de manual o en la
--help
salida del comando, pero ambos son legibles por humanos y, por lo tanto, están escritos al viento.Cuando un comando quiere obtener una entrada, la lee de su flujo de entrada o de la lista de argumentos. En ambos casos, las cadenas de texto deben analizarse.
Cuando un comando quiere devolver algo, debe
echo
hacerlo en su flujo de salida. Otra forma practicada a menudo es almacenar el valor de retorno en variables dedicadas y globales. Escribir en la secuencia de salida es más claro y más flexible, porque también puede tomar datos binarios. Por ejemplo, puede devolver un BLOB fácilmente:Como otros han escrito en este hilo, la persona que llama también puede usar la sustitución de comandos
$()
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 aclarar esto:return
(likeexit
) solo puede tomar un valor de 0-255, y los valores distintos de 0 no son necesariamente errores, como se afirma a menudo.Cuando no proporciona un valor explícito,
return
el estado se toma del último comando en una declaración / función / comando Bash, etc. Por lo tanto, siempre hay un estado yreturn
es solo una forma fácil de proporcionarlo.fuente
La
return
instrucción establece el código de salida de la función, muy similar a loexit
que hará para todo el script.El código de salida para el último comando siempre está disponible en la
$?
variable.fuente
El problema con otras respuestas es que usan un global, que puede sobrescribirse cuando hay varias funciones en una cadena de llamadas, o
echo
que su función no puede generar información de diagnóstico (olvidará que su función hace esto y el "resultado", es decir, devuelve valor, contendrá más información de la que espera la persona que llama, lo que provocará un error extraño), oeval
que es demasiado pesado y hacky.La forma correcta de hacer esto es poner las cosas de nivel superior en una función y usar una
local
regla de alcance dinámico de bash. Ejemplo:Esto salidas
¡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 lo que usan la mayoría de los lenguajes de programación. Esta es en realidad una característica documentada , fácil de pasar por alto, y no muy bien explicada, aquí está la documentación para ello (el énfasis es mío):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 generar
stdout
/stderr
pueden conectarse / out, pueden devolver un código de salida. Básicamente no hay diferencia entre definir un comando en un script y crear un ejecutable al que se pueda llamar desde la línea de comando.Entonces, en lugar de escribir su script de esta manera:
escríbelo así:
donde
main()
declararet_val
comolocal
y todas las demás funciones devuelven valores a través deret_val
.Consulte también la siguiente pregunta de Unix y Linux: Alcance de las variables locales en las funciones de Shell .
Otra solución, quizás incluso mejor según la situación, es la publicada por ya.teck que utiliza
local -n
.fuente
Otra forma de lograr esto son las referencias de nombre (requiere Bash 4.3+).
fuente
-n <name>=<reference>
hace: convierte la variable recién creada en una referencia a otra señalada por<reference>
. Se<name>
realizan tareas adicionales en la variable referenciada.Me gusta hacer lo siguiente si se ejecuta en un script donde se define la función:
Me gusta esto, porque puedo incluir declaraciones de eco en mis funciones si quiero
fuente
Como complemento de las excelentes publicaciones de otros, aquí hay un artículo que resume estas técnicas:
Valores devueltos de funciones bash
fuente
Git Bash en Windows usando matrices para múltiples valores de retorno
CODIGO BASH:
RENDIMIENTO ESPERADO:
fuente