Encaminhar declarações de função em um script Bash ou Shell?

95

Existe tal coisa bashou pelo menos algo semelhante (work-around) como declarações de encaminhamento, bem conhecidas em C / C ++, por exemplo?

Ou existe porque, por exemplo, sempre é executado em uma passagem (linha após linha)?

Se não houver declarações de encaminhamento, o que devo fazer para tornar meu script mais fácil de ler. É bastante longo e essas definições de função no início, misturadas com variáveis ​​globais, fazem meu script parecer feio e difícil de ler / entender)? Estou pedindo para aprender algumas práticas bem conhecidas / recomendadas para esses casos.


Por exemplo:

# something like forward declaration
function func

# execution of the function
func

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

Respostas:

190

Ótima pergunta. Eu uso um padrão como este para a maioria dos meus scripts:

#!/bin/bash

main() {
    foo
    bar
    baz
}

foo() {
}

bar() {
}

baz() {
}

main "$@"

Você pode ler o código de cima para baixo, mas ele realmente não começa a ser executado até a última linha. Ao passar "$@"para main () você pode acessar os argumentos de linha de comando $1, $2et al assim como você faria normalmente.

John Kugelman
fonte
3
Olá, como você estrutura os dados que devem ser compartilhados entre foo / bar / baz em seu exemplo? Normalmente, eu apenas coloco no início do script. Este ainda é o caso ao usar funções? Ou é melhor colocar dados globais em main e depois passá-los para foo / bar / baz como argumentos? Qual é a melhor prática?
bodacydo 01 de
4
Eu prefiro discussões. Exceto isso, definirei variáveis ​​globais em mainou em uma função logo após main(por exemplo, setupou parseArguments). Eu evito ter variáveis ​​globais definidas acima main- o código não deve sair de main.
John Kugelman
Isso parece um pouco análogo ao que if _ _ name _ _ == "_ _ main _ _": main()acontece em python
Sergiy Kolodyazhnyy
Isso também é fantástico ao usar ferramentas como Bats para testar seus scripts, dividir tudo em funções torna o teste de componentes individuais muito mais fácil. Veja também a postagem do blog
dragon788
30

Quando meus scripts bash crescem muito, eu uso um mecanismo de inclusão:

Arquivo allMyFunctions:

foo() {
}

bar() {
}

baz() {
}

Arquivo main:

#!/bin/bash

. allMyfunctions

foo
bar
baz
mouviciel
fonte
27
Pessoalmente, quando um script shell começa a crescer além de um arquivo, eu tendo a mudar para um idioma diferente ;-)
Joachim Sauer
Não seria melhor usar source allMyfunctions?
pydoge
4
@pydoge: sourcenão é compatível com POSIX. bashdefine sourcecomo um alias para .: eles são funcionalmente equivalentes.
mouviciel