función de llamada declarada a continuación


15

¿Es posible llamar a una función que se declara a continuación en bash?

Ejemplo

if [ "$input" = "yes" ]; then
    YES_FUNCTION
elif [ "$input" = "no" ]; then
    NO_FUNCTION
else
    exit 0;
fi

YES_FUNCTION()
{
  .....
  .....
}

NO_FUNCTION()
{
  .....
  .....
}

Respuestas:


36

Como otros han dicho, no puedes hacer eso.

Pero si desea organizar el código en un archivo para que el programa principal esté en la parte superior del archivo, y otras funciones se definen a continuación, puede hacerlo teniendo una mainfunción separada .

P.ej

#!/bin/sh

main() {
    if [ "$1" = yes ]; then
        do_task_this
    else
        do_task_that
    fi
}

do_task_this() {
    ...
} 
do_task_that() {
    ...
} 

main "$@"; exit

Cuando llamamos mainal final del archivo, todas las funciones ya están definidas. Se requiere pasar explícitamente "$@"a mainpara que los argumentos de la línea de comandos del script sean visibles en la función.

Lo explícito exiten la misma línea que la llamada a main no es obligatorio, pero puede usarse para evitar que un script en ejecución se estropee si se modifica el archivo de script. Sin él, el shell intentaría continuar leyendo los comandos del archivo de script después de los mainretornos. (consulte ¿Cómo leer todo el script de shell antes de ejecutarlo? )


@ikkachu piensa que debería funcionar ... déjame comprobar.
msp9011

77
Con los scripts de Bash, a menudo uso [[ ${BASH_SOURCE[0]} = "$0" ]] && Main "$@"para llamar a la función principal para poder obtenerlo en otro script sin Mainser ejecutado. Entonces puedo reutilizar las funciones o escribir pruebas para verificarlas.
BlackJack

11
Tener main "$@"; exit(con exiten la misma línea que main) también es útil como protección contra la modificación del archivo mientras se interpreta.
Stéphane Chazelas

2
@JoL, lo que se lee no se vuelve a leer, y el shell necesitará leer y analizar todo el texto de un bucle antes de comenzar a ejecutarlo, pero luego, cuando el bucle regrese, continuará leyendo desde el resto del archivo en la posición actual (y si el archivo ha sido modificado, arruinará las cosas). Si todo está en funciones, el shell debe leerlo todo antes de comenzar a hacer cualquier cosa (excepto definir esas funciones), si colocamos el exiten la misma línea ya que mainnos aseguramos de que el shell no volverá a leer nada del archivo después de mainregresar.
Stéphane Chazelas

1
@MontyHarder, no importa si se utiliza main; exit, main; exit $?o main <EOF>, en todo caso, el código de salida mainse utiliza como el código de salida del script. Esto exitsería solo para evitar que las cosas se estropeen si alguien edita el script mientras se está ejecutando.
ilkkachu

13

No, las funciones tienen que existir en el entorno de shells al momento de llamarlas.

La "Guía de estilo de Shell" de Google tiene una solución para esto:

Se mainrequiere una función llamada para los scripts lo suficientemente largos como para contener al menos otra función.

Al final del script, después de todas las funciones, como la única declaración que no está en una función, tendría

main "$@"

Esto llamaría a la mainfunción con cualquier parámetro que se le haya dado al script. La mainfunción podría ubicarse en la parte superior de la secuencia de comandos (la guía de estilo dice ponerla en la parte inferior, pero, de nuevo, dice muchas cosas).

Cuando el shell llega a la mainllamada, todas las funciones en el script se han analizado y, por lo tanto, se pueden llamar desde la mainfunción.


9

No, las funciones deben declararse antes de ser utilizadas. Los scripts de shell se leen línea por línea y actúan línea por línea; entonces una función no existe hasta que su declaración ha sido ejecutada.


tienes razón. El problema es que tengo más de 30 funciones en un script. Es bastante complicado cuando leemos el código. En Ces cómodo.
msp9011

3
Puede poner sus declaraciones de función en otro archivo y obtenerlo ( . yourfile).
Stephen Kitt

Sí, lo he intentado, pero el requisito es tener un solo script.
msp9011

@SivaPrasath ¿Cuál es exactamente el problema? Simplemente defina todas las funciones, tal vez incluso poner el código principal en una función y luego la última línea muestra qué función se llama y contiene la parte principal del script.
BlackJack

@SivaPrasath En C, no tiene ifdeclaraciones simples fuera de una función. La función no tiene que definirse cuando declara la iffunción que contiene, solo cuando la llama .
chepner

4

El shell no tiene el concepto de declaringuna función. Por lo tanto, no puede tener una declaración adelantada.

Como consecuencia, debe tener la implementación de la función leída por el shell antes de que pueda ser invocada.


44
Técnicamente, algunos shells (ksh, zsh) tienen una función de carga automática de funciones que podría verse como una forma de declaración (donde autoload fdeclara la función, pero su cuerpo solo se carga en la primera invocación). Sin embargo, eso no se aplica a los OP bash.
Stéphane Chazelas
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.