Retorno implícito em funções bash?

Digamos que tenho uma função bash como esta:

gmx(){ echo "foo"; } 

esta função funcionará implicitamente retornar o valor de saída do comando echo, ou usar return é necessário?

gmx(){ echo "foo"; return $? } 

Presumo que o caminho bash funciona, o status de saída do comando final da função bash é aquele que obtém “retornado”, mas não é 100% certo.

Resposta

return faz um retorno explícito de uma função shell ou” script de ponto “(um script originado). Se return não for executado, um retorno implícito é feito no final da função shell ou script de ponto.

Se return é executado sem um parâmetro, é equivalente a retornar o status de saída do comando executado mais recentemente.

É assim que return funciona em todos os POSIX shells.

Por exemplo,

gmx () { echo "foo" return "$?" } 

é, portanto, equivalente a

gmx () { echo "foo" return } 

que é o mesmo que

gmx () { echo "foo" } 

Em geral, raramente é necessário usar $? em tudo. Na verdade, ele só é necessário se você precisar salvá-lo para uso futuro, por exemplo, se precisar investigar seu valor várias vezes (nesse caso, você atribuiria seu valor a uma variável e executaria uma série de testes nessa variável). / p>

Comentários

  • Uma desvantagem de usar return é que para funções definidas como f() (...; cmd; return), evita a otimização que alguns shells fazem ao executar o cmd no mesmo processo do subshell. Com muitos shells, isso também significa que o status de saída da função não ‘ carrega a informação de que cmd foi eliminado quando (a maioria dos shells pode ‘ recuperar essas informações de qualquer maneira).
  • Observe que com pdksh e alguns de seus derivados (como OpenBSD sh ou posh), você ‘ d precisaria return -- "$?" se houvesse um chance de que o último comando foi uma função que retornou um número negativo. mksh (também baseado em pdksh) proíbe funções de retornarem valores negativos.
  • obrigado, isso ajuda, acho que não ‘ t entendo como return x funciona de maneira diferente de exit x … a única coisa que sei é que return x não sairá do processo atual.
  • @AlexanderMills Bem, ‘ é o que eu disse: return é usado para retornar de uma função ou um script de ponto. exit faz algo completamente diferente (encerra um processo).
  • sim, faz sentido, acho que estou começando a entender melhor isso

Resposta

Da página do manual bash(1):

Quando executado, o status de saída de uma função é o status de saída do último comando executado no corpo.

Comentários

  • certo, e um corolário pode ser que a instrução de retorno nada mais é do que o status de saída?
  • Acho que return é um comando embutido – embora return 1 seja diferente de exit 1, etc, então
  • ” return [n]: Faz com que uma função pare de ser executada e retorna o valor especificado por n para seu chamador. Se n for omitido, o status de retorno será o do último comando executado no corpo da função. ” (ibid) Portanto, return força o status de saída de uma função para um valor específico, se especificado.
  • @AlexandwrMills Sim, return e exit são ambos integrados, exceto return que só pode ser usado dentro da função. Você pode ‘ t encerrar um script com return. O status de saída é o valor que o comando retorna. return é o comando que retorna esse valor. Portanto, a ” instrução de retorno nada mais é do que o status de saída ” não é muito precisa. Um é um valor, o outro é comando mais valor.
  • @AlexanderMills, return retorna da função, exit sai de todo o shell. É ‘ exatamente o mesmo que em, digamos C com return vs. exit(n), ou return vs. sys.exit() em Python.

Resposta

Vou apenas adicionar algumas notas de cautela às respostas já fornecidas:

  • Embora return tenha um significado muito especial para o shell, do ponto de vista da sintaxe, é um comando interno do shell e uma instrução de retorno é analisado como qualquer outro comando simples. Então, isso significa que, como no argumento de qualquer outro comando, $? quando não cotado, estaria sujeito a divisão + glob

    Portanto, você precisa citar que $? para evitá-lo:

    return "$?" 
  • return geralmente não aceita nenhuma opção (ksh93 “s aceita o usual --help, --man, --author … embora). O único argumento esperado (opcional) é o código de retorno. O intervalo de códigos de retorno aceitos varia de shell para shell, e se algum valor fora de 0..255 é refletido corretamente em

também varia de shell para shell. Veja Código de saída padrão quando o processo é encerrado? para obter detalhes sobre isso.

A maioria dos shells aceita números negativos (afinal, o argumento passado para a _exit() / exitgroup() chamada do sistema é uma int, portanto, com valores abrangendo pelo menos – 2 31 a 2 31 -1, então só faz sentido que os shells aceitem o mesmo intervalo para suas funções).

A maioria dos shells usa o waitpid() e co. API para recuperar esse status de saída, no entanto, nesse caso, é truncado para um número entre 0 e 255 quando armazenado em $?. Mesmo chamando uma função não envolve a geração de um processo e usado waitpid() para recuperar seu status de saída, pois tudo é feito no mesmo processo, muitos shells também imitam que waitpid() comportamento ao invocar funções. O que significa que mesmo se você chamar return com um valor negativo, $? conterá um número positivo.

Agora, entre aqueles shells cujo return aceita números negativos (ksh88, ksh93, bash, zsh, pdksh e derivados diferentes de mksh, yash), existem alguns ( pdksh e yash) que precisam ser escritos como return -- -123, caso contrário -123 é considerado três -1, -2, -3 opções inválidas.

Como pdksh e seu de rivatives (como OpenBSD sh ou posh) preservam o número negativo em $?, isso significa que fazer return "$?" iria falhar quando $? contiver um número negativo (o que aconteceria quando o último comando executado fosse uma função que retornasse um número negativo ).

Portanto, return -- "$?" seria melhor nesses shells. No entanto, observe que embora seja compatível com a maioria dos shells, essa sintaxe não é POSIX e, na prática, não é compatível com mksh e derivados de ash.

Então, para resumir, com Shells baseados em pdksh, você pode usar números negativos em argumentos para funções, mas se o fizer, return "$@" não funcionará. Em outros shells, return "$@" funcionará e você deve evitar usar números negativos (ou números fora de 0..255) como argumentos para return.

  • Em todos os shells que eu conheço, chamar return de dentro de um subshell em execução dentro de uma função fará com que o subshell saia (com o status de saída fornecido, se houver, ou aquele do último comando executado), mas não causará um retorno da função (para mim, não está claro se POSIX oferece essa garantia, alguns argumentam que exit deve ser usado em vez de subshells de saída funções internas). Por exemplo

    f() { (return 3) echo "still inside f. Exit status: $?" } f echo "f exit status: $?" 

    produzirá:

    still inside f. Exit status: 3 f exit status: 0 
  • Resposta

    Sim, o valor de retorno implícito de uma função é o status de saída do último executado comando . Isso também é verdade em qualquer ponto de qualquer script de shell. Em qualquer ponto da sequência de execução do script, o status de saída atual é o status de saída do último comando executado. Mesmo comando executado como parte de uma atribuição de variável: var=$(exit 34). A diferença com as funções é que uma função pode alterar o status de saída no final da execução da função.

    A maneira alternativa de alterar o “status de saída atual” é iniciar um sub shell e encerrá-lo com qualquer status de saída necessário:

    $ $(exit 34) $ echo "$?" 34 

    E sim, o status de saída expansão precisam ser citados:

    $ IFS="123" $ $(exit 34) $ echo $? 4 

    Um (exit 34) também funciona.
    Alguns podem argumentar que uma construção mais robusta deve ser $(return 34), e que uma saída deve “sair” do script que está sendo executado. Mas $(return 34) não funciona com qualquer versão do bash. Portanto, não é portátil.

    A maneira mais segura de definir um status de saída é usá-lo como foi projetado para funcionar, definir e return a partir de uma função :

    exitstatus(){ return "${1:-"$?"}"; } 

    Então, no final de uma função. é exatamente equivalente a nada ou return ou return "$?". O final de uma função não precisa significar a “última linha de código de uma função”.

    #!/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 } 

    Irá imprimir:

    $ ./script foo 78 baz 89 baz 90 

    O único uso prático para "$?" é imprimir seu valor: echo "$?" ou armazenar em uma variável (pois é um valor efêmero e muda a cada comando executado): exitstatus=$? (lembre-se de citar a variável em comandos como export EXITSTATUS="$?".

    No comando return, o intervalo válido de valores é geralmente de 0 a 255, mas entenda que os valores de 126 + n são usados por alguns shells para sinalizar o status de saída especial, portanto, a recomendação geral é usar 0-125.

    Deixe uma resposta

    O seu endereço de email não será publicado. Campos obrigatórios marcados com *