função de chamada declarada abaixo

15

É possível chamar uma função que é declarada abaixo no bash?

Exemplo

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

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

NO_FUNCTION()
{
  .....
  .....
}
msp9011
fonte

Respostas:

36

Como outros já disseram, você não pode fazer isso.

Mas se você deseja organizar o código em um arquivo para que o programa principal fique na parte superior do arquivo e outras funções sejam definidas abaixo, você poderá fazê-lo tendo uma mainfunção separada .

Por exemplo

#!/bin/sh

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

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

main "$@"; exit

Quando chamamos mainno final do arquivo, todas as funções já estão definidas. É necessário passar explicitamente "$@"para mainpara tornar os argumentos da linha de comandos do script visíveis na função.

O explícito exitna mesma linha que a chamada para main não é obrigatório, mas pode ser usado para impedir que um script em execução seja prejudicado se o arquivo de script for modificado. Sem ele, o shell tentaria continuar lendo os comandos do arquivo de script após mainretornos. (consulte Como ler o script de shell inteiro antes de executá-lo? )

ilkkachu
fonte
@ikkachu acho que deve funcionar .. deixe-me verificar.
msp9011
7
Nos scripts Bash, costumo usar [[ ${BASH_SOURCE[0]} = "$0" ]] && Main "$@"a função principal para chamar a fonte em outro script sem Mainser executada. Então eu posso reutilizar as funções ou escrever testes para verificá-las.
precisa
11
Ter main "$@"; exit(com exita mesma linha que main) também é útil como proteção contra o arquivo sendo modificado enquanto é interpretado.
Stéphane Chazelas
2
@JoL, o que é lido não é lido novamente, e o shell precisará ler e analisar todo o texto de um loop antes de começar a executá-lo, mas depois que o loop retornar, ele continuará lendo o restante do arquivo em a posição atual (e se o arquivo tiver sido modificado, ele estragará tudo). Se tudo estiver em funções, o shell precisará ler tudo antes de começar a fazer qualquer coisa (exceto definir essas funções), se colocarmos exita mesma linha para maingarantir que o shell não leia nada novamente do arquivo após o mainretorno.
Stéphane Chazelas
1
@MontyHarder, não importa se você usa main; exit, main; exit $?ou main <EOF>, em todos os casos o código de saída mainé usado como o código de saída do script. A exitseria apenas para evitar que as coisas ficar confuso se alguém edita o roteiro enquanto ele está funcionando.
22918 ilkkachu
13

Não, as funções precisam existir no ambiente de shells no momento de chamá-las.

O "Guia de estilos de shell" do Google tem uma correção para isso:

Uma função chamada mainé necessária para scripts longos o suficiente para conter pelo menos uma outra função.

No final do script, depois de todas as funções, como a única instrução que não está em uma função, você teria

main "$@"

Isso chamaria a mainfunção com quaisquer parâmetros que o script foi fornecido. A mainfunção pode estar localizada na parte superior do script (o guia de estilo diz para colocá-la na parte inferior, mas, novamente, diz muitas coisas).

Quando o shell chega à mainchamada, todas as funções no script foram analisadas e, portanto, podem ser chamadas de dentro da mainfunção.

Kusalananda
fonte
9

Não, as funções precisam ser declaradas antes de serem usadas. Os scripts do shell são lidos linha a linha e atuados linha a linha; portanto, uma função não existe até que sua declaração seja executada.

Stephen Kitt
fonte
Você está certo. o problema é que tenho mais de 30 funções em um script. é bastante complicado quando lemos o código. Em Cque é confortável.
msp9011
3
Você pode colocar suas declarações de função em outro arquivo e fonte ( . yourfile).
Stephen Kitt
Sim, eu tentei isso, mas o requisito é ter um único script.
msp9011
@SivaPrasath Qual é exatamente o problema? Apenas defina todas as funções, talvez até coloque o código principal em uma função e, em seguida, a última linha mostra qual função é chamada e contém a parte principal do script.
precisa
@SivaPrasath Em C, você não tem ifinstruções simples fora de uma função. A função não precisa ser definida quando você declara a iffunção -contain, apenas quando a chama .
chepner
4

O shell não tem conceito de declaringfunção. Portanto, você não pode ter uma declaração direta.

Como conseqüência, você precisa que a implementação da função seja lida pelo shell antes de poder ser chamada.

esperto
fonte
4
Tecnicamente, alguns shells (ksh, zsh) têm um recurso de carregamento automático de função que pode ser visto como uma forma de declaração (onde autoload fdeclara a função, mas seu corpo é carregado apenas na primeira chamada). Isso não se aplica aos OPs bash.
Stéphane Chazelas