¿Reenviar declaraciones de funciones en un script Bash o Shell?

95

¿Existe tal cosa en basho al menos algo similar (solución alternativa) como declaraciones hacia adelante, bien conocidas en C / C ++, por ejemplo?

¿O existe tal cosa porque, por ejemplo, siempre se ejecuta en una pasada (línea tras línea)?

Si no hay declaraciones de reenvío, ¿qué debo hacer para que mi script sea más fácil de leer? ¿Es bastante largo y estas definiciones de funciones al principio, mezcladas con variables globales, hacen que mi script se vea feo y difícil de leer / entender)? Pido aprender algunas prácticas recomendadas / bien conocidas para estos casos.


Por ejemplo:

# something like forward declaration
function func

# execution of the function
func

# definition of func
function func
{
    echo 123
}
Kiril Kirov
fuente

Respuestas:

190

Gran pregunta. Utilizo un patrón como este para la mayoría de mis scripts:

#!/bin/bash

main() {
    foo
    bar
    baz
}

foo() {
}

bar() {
}

baz() {
}

main "$@"

Puede leer el código de arriba a abajo, pero en realidad no comienza a ejecutarse hasta la última línea. Al hacer pasar "$@"a main () se puede acceder a los argumentos de línea de comandos $1, $2et al igual que lo haría normalmente.

John Kugelman
fuente
3
Hola, ¿cómo se estructuran los datos que se deben compartir entre foo / bar / baz en su ejemplo? Por lo general, lo pongo al principio del guión. ¿Sigue siendo así cuando se utilizan funciones? ¿O es mejor poner datos globales en main y luego pasarlos a foo / bar / baz como argumentos? ¿Cuál es la mejor práctica?
bodacydo
4
Prefiero los argumentos. Salvo eso, estableceré variables globales en maino en una función justo después main(por ejemplo, setupo parseArguments). Evito tener variables globales configuradas arriba main; el código no debe salir de main.
John Kugelman
Esto parece algo análogo a lo que if _ _ name _ _ == "_ _ main _ _": main()hace en Python
Sergiy Kolodyazhnyy
Esto también es fantástico cuando se usan herramientas como Bats para probar sus scripts, dividir todo en funciones hace que probar los componentes individuales sea mucho más fácil. Véase también la publicación del blog
dragon788
30

Cuando mis scripts bash crecen demasiado, uso un mecanismo de inclusión:

Archivo allMyFunctions:

foo() {
}

bar() {
}

baz() {
}

Archivo main:

#!/bin/bash

. allMyfunctions

foo
bar
baz
Mouviciel
fuente
27
Personalmente, cuando un script de shell comienza a crecer más allá de un archivo, tiendo a cambiar a un idioma diferente ;-)
Joachim Sauer
¿No sería mejor usarlo source allMyfunctions?
Pydoge
4
@pydoge: sourceno es compatible con POSIX. bashdefine sourcecomo un alias a .: son funcionalmente equivalentes.
mouviciel