Digamos que tengo una función bash como esta:
gmx(){ echo "foo"; }
¿funcionará implícitamente? devolver el valor de salida del comando echo
, o es necesario utilizar return?
gmx(){ echo "foo"; return $? }
Supongo que la forma bash funciona, el estado de salida del comando final de la función bash es el que se «devuelve», pero no es 100% seguro.
Respuesta
return
hace un retorno explícito desde una función de shell o» dot script «(un script de origen). Si return
no se ejecuta, se realiza una devolución implícita al final de la función de shell o el script dot.
Si return
se ejecuta sin un parámetro, es equivalente a devolver el estado de salida del comando ejecutado más recientemente.
Así es como return
funciona en todos los POSIX shells.
Por ejemplo,
gmx () { echo "foo" return "$?" }
es equivalente a
gmx () { echo "foo" return }
que es lo mismo que
gmx () { echo "foo" }
En general, es muy raro que necesite usar $?
en absoluto. En realidad, solo es necesario si necesita guardarlo para uso futuro, por ejemplo, si necesita investigar su valor varias veces (en cuyo caso, asignaría su valor a una variable y realizaría una serie de pruebas en esa variable).
Comentarios
Respuesta
Desde la bash(1)
página de manual:
Cuando se ejecuta, el estado de salida de una función es el estado de salida del último comando ejecutado en el cuerpo.
Comentarios
- correcto, y un corolario podría ser que la declaración de retorno no es más que el estado de salida.
- Supongo que
return
es un comando incorporado, aunquereturn 1
es diferente deexit 1
, etc., así que - » return [n]: hace que una función deje de ejecutarse y devuelva el valor especificado por n a su llamador. Si se omite n, el estado de retorno es el del último comando ejecutado en el cuerpo de la función. » (ibid) Entonces,
return
fuerza el estado de salida de una función a un valor específico si se especifica. - @AlexandwrMills Sí,
return
yexit
son ambos integrados, excepto quereturn
solo se puede usar dentro de la función. Puede ‘ t terminar un script conreturn
. El estado de salida es el valor que devuelve el comando.return
es un comando que devuelve ese valor. Entonces, la » declaración de retorno no es más que el estado de salida » simplemente no es del todo precisa. Uno es un valor, el otro es el comando más el valor. - @AlexanderMills,
return
regresa de la función,exit
sale de todo el caparazón. Es ‘ exactamente igual que en, digamos C conreturn
frente aexit(n)
, oreturn
frente asys.exit()
en Python.
Respuesta
Solo agregaré algunas notas de precaución a las respuestas ya proporcionadas:
-
Aunque
return
tiene un significado muy especial para el shell, desde el punto de vista de la sintaxis, es un comando incorporado del shell y una declaración de retorno se analiza como cualquier otro comando simple. Eso significa que, como en el argumento de cualquier otro comando,$?
cuando no se cita, estaría sujeto a split + globPor lo tanto, debe citar
$?
para evitarlo:return "$?"
-
return
normalmente no «acepta ninguna opción (ksh93
» s acepta las--help
,--man
,--author
… aunque). El único argumento que espera (opcional) es el código de retorno. El rango de códigos de retorno aceptados varía de capa a capa, y si cualquier valor fuera de 0..255 se refleja correctamente en
también varía de un shell a otro. Consulte ¿Código de salida predeterminado cuando se termina el proceso? para obtener detalles al respecto.
La mayoría de las shells aceptan números negativos (después de todo, el argumento pasado a la llamada del sistema _exit()
/ exitgroup()
es una int
, por lo que los valores abarcan al menos – 2 31 a 2 31 -1, por lo que solo tiene sentido que los shells acepten el mismo rango para sus funciones).
La mayoría de los shells usan waitpid()
y co. API para recuperar ese estado de salida; sin embargo, en cuyo caso, se trunca a un número entre 0 y 255 cuando se almacena en $?
. Aunque se invoca una función no implica generar un proceso y usó waitpid()
para recuperar su estado de salida ya que todo se hace en el mismo proceso, muchos shells también imitan que waitpid()
comportamiento al invocar funciones. Lo que significa que incluso si llamas a return
con un valor negativo, $?
contendrá un número positivo.
Ahora, entre los shells cuyo return
acepta números negativos (ksh88, ksh93, bash, zsh, pdksh y derivados distintos de mksh, yash), hay algunos ( pdksh y yash), que deben escribirse como return -- -123
, de lo contrario, -123
se toma como tres -1
, -2
, -3
opciones no válidas.
Como pdksh y su rivatives (como OpenBSD sh
o posh
) conservan el número negativo en $?
, eso significa que hacer return "$?"
fallaría cuando $?
contiene un número negativo (lo que sucedería cuando el último comando de ejecución fuera una función que devolviera un número negativo ).
Entonces return -- "$?"
sería mejor en esos shells. Sin embargo, tenga en cuenta que, si bien es compatible con la mayoría de los shells, esa sintaxis no es POSIX y, en la práctica, no es compatible con mksh
y derivados de ash.
Entonces, para resumir, shells basados en pdksh, puede usar números negativos en los argumentos de las funciones, pero si lo hace, return "$@"
no funcionará. En otros shells, return "$@"
funcionará y debe evitar el uso de números negativos (o números fuera de 0..255) como argumentos para return
.
En todos los shells que conozco, llamar a return
desde el interior de un subshell que se ejecuta dentro de una función hará que el subshell salga (con el estado de salida proporcionado si lo hay o el del último comando ejecutar), pero de otra manera no causará un retorno de la función (para mí, no está claro si POSIX le brinda esa garantía, algunos argumentan que exit
debe usarse en lugar de subcapas de salida funciones internas). Por ejemplo
f() { (return 3) echo "still inside f. Exit status: $?" } f echo "f exit status: $?"
generará:
still inside f. Exit status: 3 f exit status: 0
Respuesta
Sí, el valor de retorno implícito de una función es el estado de salida de la última ejecutada comando. Eso también es cierto en cualquier punto de cualquier script de shell. En cualquier punto de la secuencia de ejecución del script, el estado de salida actual es el estado de salida del último comando ejecutado. Incluso comando ejecutado como parte de una asignación de variable: var=$(exit 34)
. La diferencia con las funciones es que una función podría cambiar el estado de salida al final de la ejecución de la función.
La forma alternativa de cambiar el «estado de salida actual» es iniciar un sub shell y salir con cualquier estado de salida necesario:
$ $(exit 34) $ echo "$?" 34
Y sí, el estado de salida expansión es necesario citar:
$ IFS="123" $ $(exit 34) $ echo $? 4
Un (exit 34)
también funciona.
Algunos pueden argumentar que una construcción más robusta debería ser $(return 34)
, y que una salida debería «salir» del script que se está ejecutando. Pero $(return 34)
no funciona con ninguna versión de bash. Por lo tanto, no es portátil.
La forma más segura de establecer un estado de salida es usarlo ya que fue diseñado para funcionar, definir y return
desde una función :
exitstatus(){ return "${1:-"$?"}"; }
Entonces, al final de una función. es exactamente equivalente a no tener nada o return
o return "$?"
. El final de una función no tiene por qué significar la «última línea de código de una función».
#!/bin/sh exitstatus(){ a="${1:-"$?"}"; return "$a"; } gmx(){ if [ "$1" = "one" ]; then printf "foo "; exitstatus 78 return "$?" elif [ "$1" = "two" ]; then printf "baz "; exitstatus 89 return else printf "baz "; exitstatus 90 fi }
Se imprimirá:
$ ./script foo 78 baz 89 baz 90
El único uso práctico de "$?"
es imprimir su valor: echo "$?"
o almacenar en una variable (ya que es un valor efímero y cambia con cada comando ejecutado): exitstatus=$?
(recuerde citar la variable en comandos como export EXITSTATUS="$?"
.
En el comando return
, el rango válido de valores es generalmente de 0 a 255, pero entienda que los valores de 126 + n
son utilizados por algunos shells para señalar un estado de salida especial, por lo que la recomendación general es utilizar 0-125.
return
es que para funciones definidas comof() (...; cmd; return)
, evita la optimización que hacen algunos shells al ejecutarcmd
en el mismo proceso que el subshell. Con muchos shells, eso también significa que el estado de salida de la función no ‘ t lleva la información de quecmd
se ha eliminado cuando se ha (la mayoría de los shells pueden ‘ t recuperar esa información de todos modos).sh
oposh
), ‘ necesitaríasreturn -- "$?"
si hubiera posibilidad de que el último comando fuera una función que devolviera un número negativo.mksh
(también basado en pdksh) prohíbe que las funciones devuelvan valores negativos.return x
funciona de manera diferente aexit x
… lo único que sé es quereturn x
no saldrá del proceso actual.return
se usa para regresar desde una función o un script de puntos.exit
hace algo completamente diferente (termina un proceso).