Protip: digite help <command>seu shell para obter informações sobre o que um shell incorporado fará. No seu caso help returnehelp exit
SiegeX 12/12/10
Respostas:
318
A partir man bashde return [n];
Faz com que uma função pare de executar e retorne o valor especificado por n ao seu chamador. Se n for omitido, o status de retorno é o do último comando executado no corpo da função.
... em exit [n]:
Faça com que o shell saia com o status n. Se n for omitido, o status de saída é o do último comando executado. Uma interceptação em EXIT é executada antes que o shell termine.
EDITAR:
Conforme sua edição da pergunta, em relação aos códigos de saída, returnnada tem a ver com códigos de saída. Os códigos de saída destinam-se a aplicativos / scripts , não a funções. Portanto, a este respeito, a única palavra-chave que define o código de saída do script (aquele que pode ser capturado pelo programa de chamada usando a $?variável shell) é exit.
EDIT 2:
Minha última declaração referente exitestá causando alguns comentários. Foi feito para diferenciar returne exitpara o entendimento do OP e, de fato, em qualquer ponto determinado de um script de programa / shell, exité a única maneira de finalizar o script com um código de saída para o processo de chamada.
Cada comando executado no shell produz um local "código de saída": ele define a $?variável para que o código, e pode ser usado com if, &&e outros operadores para condicionalmente executar outros comandos.
Esses códigos de saída (e o valor da $?variável) são redefinidos a cada execução de comando.
Aliás, o código de saída do último comando executado pelo script é usado como o código de saída do próprio script, conforme visto pelo processo de chamada.
Finalmente, as funções, quando chamadas, agem como comandos do shell em relação aos códigos de saída. O código de saída da função ( dentro da função) é definido usando return. Portanto, quando uma função return 0é executada, a execução da função termina, fornecendo um código de saída 0.
Não exatamente. Ele sempre retorna um valor do shell atual. Não importa se você está dentro de uma função ou não.
Diego Sevilla
10
Comente sua edição: posso estar confundindo valores de retorno e códigos de saída, mas func(){ return 50; };func;echo $?ecoa 50. Portanto, a $?variável shell não parece estar limitada a exit.
lecodesportif 12/12
8
" $?Expande para o status de saída do pipeline de primeiro plano executado mais recentemente." Essa saída pode ser do shell na forma de uma chamada para exit(ou chegar ao final do script) ou na forma de uma chamada para returndentro de uma função.
SiegeX
11
@lecodesportif: O $?processo / script atual é limitado exitao resultado do último comando executado por este script ou ao resultado. Portanto, se sua última linha de script é a chamada para essa função e essa função retorna 50, sim, a $?que você produz para o processo que chamou você é 50. No entanto, isso não tem a ver com o returnporque é restrito ao script atual. Só será retornado se essa chamada de função for a última frase do script. exit, no entanto, sempre termine o script e retorne esse valor $?ao processo de chamada .
Diego Sevilla
11
-1 por me confundir com a linha " returnnão tem nada a ver com códigos de saída". A experiência me diz que não há diferença funcional entre o código de retorno de uma função e o código de saída de um script.
23415 Jack
296
returnfará com que a função atual fique fora do escopo, enquanto exitfará com que o script termine no ponto em que é chamado. Aqui está um exemplo de programa para ajudar a explicar isso:
#!/bin/bash
retfunc(){
echo "this is retfunc()"return1}
exitfunc(){
echo "this is exitfunc()"
exit 1}
retfunc
echo "We are still here"
exitfunc
echo "We will never see this"
Resultado
$ ./test.sh
this is retfunc()We are still here
this is exitfunc()
Belo exemplo. Você também pode mostrar o valor de saída de 1 pol $?.
Diego Sevilla
48
Observe que essa função NÃO imprimirá "Ainda estamos aqui" se você adicionar "set -e" antes da chamada para "retfunc".
Michael
4
No entanto, echo fnord | while read x; do exitfunc; done; echo "still here"imprimirá "ainda aqui". Parece que apenas o whilesub-shell é encerrado neste cenário.
Tripleee
Uma solução aproximada é, done || exit $?porém, feia e não exatamente equivalente.
Tripleee
2
+1 Pode ser útil adicionar: `` ` returnfará com que a função atual ou o script de origem fiquem fora do escopo```.
Isaac
56
Não acho que alguém tenha realmente respondido totalmente à pergunta porque não descreve como os dois são usados. OK, acho que sabemos que exit mata o script, onde quer que seja chamado e você pode atribuir um status a ele, como sair ou sair 0 ou sair 7 e assim por diante. Isso pode ser usado para determinar como o script foi forçado a parar se chamado por outro script, etc. Chega na saída.
return quando chamado retornará o valor especificado para indicar o comportamento da função, geralmente 1 ou 0. Por exemplo:
#!/bin/bash
isdirectory(){if[-d "$1"]thenreturn0elsereturn1fi
echo "you will not see anything after the return like this text"}
verifique assim:
if isdirectory $1;then echo "is directory";else echo "not a directory";fi
ou assim:
isdirectory || echo "not a directory"
Neste exemplo, o teste pode ser usado para indicar se o diretório foi encontrado. observe que nada após o retorno não será executado na função. 0 é verdadeiro, mas falso é 1 no shell, diferente de outros programas.
Ou apenas use test -d $1para obter o mesmo resultado. Nunca faça if <check> return else return. <check>sozinho fará a mesma coisa em todos os idiomas que conheço pelo menos.
Erikbwork
4
Para ser ainda mais explícito sobre o que erik está dizendo: isdirectory() { [ -d "$1" ]; }se comportará exatamente como o que você tem aqui: O valor de retorno padrão de uma função shell, seja atingindo o final de seu código ou por um returnsem argumentos, é o comando mais recente.
Charles Duffy
11
Os outros comentaristas aqui estão criticando o estilo do exemplo de Mike Q, quando ele realmente está falando sobre o comportamento da returndeclaração. É verdade que seu exemplo é simplista e não deve ser usado na produção. Mas é simples, por isso realiza sua tarefa muito bem. Nada de errado com isso.
Mike S
Obrigado Mike S, sim, eu concordo que o exemplo mais simples explica melhor saída x retorno. Os outros comentários são certamente válida, e deve ser considerado para mais codificadores festança avançada ;-)
Mike Q
1
Alguns podem dizer que não está exatamente relacionado à pergunta, mas está relacionado e respondeu ao problema que tive que me levou a encontrar essa pergunta. :-)
Jesse Steele
33
Lembre-se de que as funções são internas a um script e normalmente retornam de onde foram chamadas usando a instrução return. Chamar um script externo é outra questão inteiramente, e os scripts geralmente terminam com uma instrução de saída.
A diferença "entre a declaração de retorno e saída nas funções BASH em relação aos códigos de saída" é muito pequena. Ambos retornam um status, não valores per se. Um status zero indica sucesso, enquanto qualquer outro status (1 a 255) indica uma falha. A instrução de retorno retornará ao script de onde foi chamada, enquanto a instrução de saída encerrará o script inteiro de onde for encontrado.
return0# returns to where the function was called. $? contains 0 (success).return1# returns to where the function was called. $? contains 1 (failure).
exit 0# exits the script completely. $? contains 0 (success).
exit 1# exits the script completely. $? contains 1 (failure).
Se sua função simplesmente terminar sem nenhuma instrução de retorno, o status do último comando executado será retornado como o código de status (e será colocado em $?).
Lembre-se de retornar e sair devolvendo um código de status de 0 a 255, disponível em $?. Você não pode inserir mais nada em um código de status (por exemplo, retornar "cat"); isso não vai funcionar. Porém, um script pode transmitir 255 motivos diferentes de falha usando códigos de status.
Você pode definir variáveis contidas no script de chamada ou fazer eco dos resultados na função e usar a substituição de comandos no script de chamada; mas o objetivo do retorno e da saída é passar códigos de status, não valores ou resultados de computação, como seria de esperar em uma linguagem de programação como C.
Mas quando apenas executo o a.sh, recebo um erro return: can only 'return' from a function or sourced script, o que o torna inadequado para um script geral.
Peter - Restabelece Monica
No nível superior de um script, nenhum deles é adequado em allsituações. Usar .ou sourceexecutar o script no shell atual, em vez de gerar um sub shell. O script precisa saber como deve ser usado. Ai do usuário que faz o contrário. Pessoalmente, recomendo a leitura de scripts antes de executá-los pela primeira vez.
Jesse Chisholm
3
Um truque incrível que eu me deparei é usar uma trapfunção ERR EXITe, em seguida, primeiro salvar o código de saída de um comando com falha errCode=$?e sair do script (de origem ou não) com o local return $errCode || exit $errCodeonde os ||meios "se eu não puder retornar porque não foi de origem" , basta sair ".
precisa saber é o seguinte
6
Em palavras simples (principalmente para iniciantes em codificação), podemos dizer,
`return`: exits the function,`exit()`: exits the program(called as process while running)
Além disso, se você observou, isso é muito básico, mas ...,
`return`: is the keyword
`exit()`: is the function
Em um script bash, exitnão é mais ou menos uma função do que return. Eles são comandos internos. Nem são palavras reservadas.
Peter - Restabelecer Monica
6
exitencerrar o processo atual ; com ou sem código de saída, considere isso um sistema mais que uma função do programa. Observe que, ao fazer o sourcing, exito shell será finalizado; no entanto, ao executar, será apenas exito script.
returnde uma função, volte para a instrução após a chamada, com ou sem um código de retorno. returné opcional e está implícito no final da função. returnsó pode ser usado dentro de uma função.
Quero acrescentar que, enquanto estiver sendo originado, não é fácil para exito script de dentro de uma função sem matar o shell. Eu acho que um exemplo é melhor em um script de 'teste'
#!/bin/bashfunction die(){
echo ${1:=Something terrible wrong happen}#... clean your trash
exit 1}[-f /whatever/]|| die "whatever is not available"# now we can proceed
echo "continue"
fazendo o seguinte:
user$ ./test
Whatever is not available
user$
test - e - a concha será fechada.
user$ ../test
Whatever is not available
somente testterminará e o prompt será exibido.
A solução é incluir o potencial procedimento em (e)
#!/bin/bashfunction die(){
echo $(1:=Something terrible wrong happen)#... clean your trash
exit 1}(# added [-f /whatever/]|| die "whatever is not available"# now we can proceed
echo "continue")# added
Adicionar o bloco (e )colocar esse bloco em um sub shell, efetivamente desabilitando o .comando (origem) como se você tivesse executado o script de teste normalmente, que está em um sub shell. IO script não é executado com .ou sourceentão você possui efetivamente 2 sub-shells.
Jesse Chisholm
3
A pergunta do OP: Qual é a diferença entre a declaração de retorno e saída nas funções BASH em relação aos códigos de saída?
Por fim, alguns esclarecimentos são necessários:
Uma instrução (return | exit) não é necessária para finalizar a execução de uma (função | shell). Uma (função | shell) será finalizada quando chegar ao final de sua lista de códigos, mesmo sem a declaração (return | exit).
Uma instrução (return | exit) não é necessária para passar um valor de volta de um terminado (função | shell). Todo processo possui uma variável interna $? que sempre tem um valor numérico. É uma variável especial que não pode ser definida como "? = 1", mas é definida apenas de maneiras especiais (veja abaixo *). O valor de $? após o último comando a ser executado no (chamado sub-função | função) é o valor que é passado de volta para o (chamador | função-pai | shell). Isso é verdade se o último comando executado é ("return [n]" | "exit [n]") ou simples ("return" ou qualquer outra coisa que por acaso seja o último comando no código de funções chamado.
Na lista de marcadores acima, escolha entre "(x | y)" sempre o primeiro item ou sempre o segundo item para obter instruções sobre funções e retorno ou shells e saída, respectivamente.
O que está claro é que ambos compartilham o uso comum da variável especial $? para passar valores para cima depois que eles terminam.
* Agora, para as formas especiais que $? Pode ser configurado:
Quando uma função chamada termina e retorna ao chamador, $? no chamador será igual ao valor final de $? na função finalizada.
Quando um shell pai espera implicitamente ou explicitamente em um único sub shell e é liberado pelo término desse sub shell, então $? no shell pai será igual ao valor final de $? no sub shell finalizado.
Algumas funções internas podem modificar $? dependendo do resultado deles. Mas alguns não.
Funções internas "return" e "exit", quando seguidas por um argumento numérico, tanto $? com argumento e encerre a execução.
Vale a pena notar que $? pode ser atribuído um valor chamando exit em um sub shell, assim:
Na verdade não! Você está logicamente errado. Sair é uma função enquanto returné uma palavra-chave. O retorno é muito mais do que apenas códigos de saída, e é por isso que a comparação não é justa.
Ahmad Awais
Eu o editei para deixar mais claro o que estava tentando mostrar. Obrigado por me ajudar a fazer isso.
Ahmad Awais
4
Nem exitnem returnsão "palavras-chave", ou, como os festança chamadas manuais eles "palavras reservadas". Também não é uma "função", no sentido de uma função bash. Ambos são comandos internos, no idioma do bash. (Não é uma função C biblioteca padrão chamado exit(), e a linguagem de programação C tem uma palavra reservada return, mas aqueles que não deve ser confundido com os comandos bash, apesar de sua semântica são curiosamente similar.)
help <command>
seu shell para obter informações sobre o que um shell incorporado fará. No seu casohelp return
ehelp exit
Respostas:
A partir
man bash
dereturn [n]
;... em
exit [n]
:EDITAR:
Conforme sua edição da pergunta, em relação aos códigos de saída,
return
nada tem a ver com códigos de saída. Os códigos de saída destinam-se a aplicativos / scripts , não a funções. Portanto, a este respeito, a única palavra-chave que define o código de saída do script (aquele que pode ser capturado pelo programa de chamada usando a$?
variável shell) éexit
.EDIT 2:
Minha última declaração referente
exit
está causando alguns comentários. Foi feito para diferenciarreturn
eexit
para o entendimento do OP e, de fato, em qualquer ponto determinado de um script de programa / shell,exit
é a única maneira de finalizar o script com um código de saída para o processo de chamada.Cada comando executado no shell produz um local "código de saída": ele define a
$?
variável para que o código, e pode ser usado comif
,&&
e outros operadores para condicionalmente executar outros comandos.Esses códigos de saída (e o valor da
$?
variável) são redefinidos a cada execução de comando.Aliás, o código de saída do último comando executado pelo script é usado como o código de saída do próprio script, conforme visto pelo processo de chamada.
Finalmente, as funções, quando chamadas, agem como comandos do shell em relação aos códigos de saída. O código de saída da função ( dentro da função) é definido usando
return
. Portanto, quando uma funçãoreturn 0
é executada, a execução da função termina, fornecendo um código de saída 0.fonte
func(){ return 50; };func;echo $?
ecoa 50. Portanto, a$?
variável shell não parece estar limitada aexit
.$?
Expande para o status de saída do pipeline de primeiro plano executado mais recentemente." Essa saída pode ser do shell na forma de uma chamada paraexit
(ou chegar ao final do script) ou na forma de uma chamada parareturn
dentro de uma função.$?
processo / script atual é limitadoexit
ao resultado do último comando executado por este script ou ao resultado. Portanto, se sua última linha de script é a chamada para essa função e essa função retorna 50, sim, a$?
que você produz para o processo que chamou você é 50. No entanto, isso não tem a ver com oreturn
porque é restrito ao script atual. Só será retornado se essa chamada de função for a última frase do script.exit
, no entanto, sempre termine o script e retorne esse valor$?
ao processo de chamada .return
não tem nada a ver com códigos de saída". A experiência me diz que não há diferença funcional entre o código de retorno de uma função e o código de saída de um script.return
fará com que a função atual fique fora do escopo, enquantoexit
fará com que o script termine no ponto em que é chamado. Aqui está um exemplo de programa para ajudar a explicar isso:Resultado
fonte
$?
.echo fnord | while read x; do exitfunc; done; echo "still here"
imprimirá "ainda aqui". Parece que apenas owhile
sub-shell é encerrado neste cenário.done || exit $?
porém, feia e não exatamente equivalente.return
fará com que a função atual ou o script de origem fiquem fora do escopo```.Não acho que alguém tenha realmente respondido totalmente à pergunta porque não descreve como os dois são usados. OK, acho que sabemos que exit mata o script, onde quer que seja chamado e você pode atribuir um status a ele, como sair ou sair 0 ou sair 7 e assim por diante. Isso pode ser usado para determinar como o script foi forçado a parar se chamado por outro script, etc. Chega na saída.
return quando chamado retornará o valor especificado para indicar o comportamento da função, geralmente 1 ou 0. Por exemplo:
verifique assim:
ou assim:
Neste exemplo, o teste pode ser usado para indicar se o diretório foi encontrado. observe que nada após o retorno não será executado na função. 0 é verdadeiro, mas falso é 1 no shell, diferente de outros programas.
Para obter mais informações sobre funções: http://www.linuxjournal.com/content/return-values-bash-functions
NOTA: A função isdirectory é apenas para fins instrucionais. Não deve ser assim que você executa essa opção em um script real.
fonte
test -d $1
para obter o mesmo resultado. Nunca façaif <check> return else return
.<check>
sozinho fará a mesma coisa em todos os idiomas que conheço pelo menos.isdirectory() { [ -d "$1" ]; }
se comportará exatamente como o que você tem aqui: O valor de retorno padrão de uma função shell, seja atingindo o final de seu código ou por umreturn
sem argumentos, é o comando mais recente.return
declaração. É verdade que seu exemplo é simplista e não deve ser usado na produção. Mas é simples, por isso realiza sua tarefa muito bem. Nada de errado com isso.Lembre-se de que as funções são internas a um script e normalmente retornam de onde foram chamadas usando a instrução return. Chamar um script externo é outra questão inteiramente, e os scripts geralmente terminam com uma instrução de saída.
A diferença "entre a declaração de retorno e saída nas funções BASH em relação aos códigos de saída" é muito pequena. Ambos retornam um status, não valores per se. Um status zero indica sucesso, enquanto qualquer outro status (1 a 255) indica uma falha. A instrução de retorno retornará ao script de onde foi chamada, enquanto a instrução de saída encerrará o script inteiro de onde for encontrado.
Se sua função simplesmente terminar sem nenhuma instrução de retorno, o status do último comando executado será retornado como o código de status (e será colocado em
$?
).Lembre-se de retornar e sair devolvendo um código de status de 0 a 255, disponível em
$?
. Você não pode inserir mais nada em um código de status (por exemplo, retornar "cat"); isso não vai funcionar. Porém, um script pode transmitir 255 motivos diferentes de falha usando códigos de status.Você pode definir variáveis contidas no script de chamada ou fazer eco dos resultados na função e usar a substituição de comandos no script de chamada; mas o objetivo do retorno e da saída é passar códigos de status, não valores ou resultados de computação, como seria de esperar em uma linguagem de programação como C.
fonte
Às vezes, você executa um script usando
.
ousource
.Se você incluir um
exit
noa.sh
, ele não apenas encerrará o script, mas também encerrará sua sessão do shell.Se você incluir um
return
noa.sh
, ele simplesmente interromperá o processamento do script.fonte
return: can only 'return' from a function or sourced script
, o que o torna inadequado para um script geral.all
situações. Usar.
ousource
executar o script no shell atual, em vez de gerar um sub shell. O script precisa saber como deve ser usado. Ai do usuário que faz o contrário. Pessoalmente, recomendo a leitura de scripts antes de executá-los pela primeira vez.trap
funçãoERR EXIT
e, em seguida, primeiro salvar o código de saída de um comando com falhaerrCode=$?
e sair do script (de origem ou não) com o localreturn $errCode || exit $errCode
onde os||
meios "se eu não puder retornar porque não foi de origem" , basta sair ".Em palavras simples (principalmente para iniciantes em codificação), podemos dizer,
Além disso, se você observou, isso é muito básico, mas ...,
fonte
exit
não é mais ou menos uma função do quereturn
. Eles são comandos internos. Nem são palavras reservadas.exit
encerrar o processo atual ; com ou sem código de saída, considere isso um sistema mais que uma função do programa. Observe que, ao fazer o sourcing,exit
o shell será finalizado; no entanto, ao executar, será apenasexit
o script.return
de uma função, volte para a instrução após a chamada, com ou sem um código de retorno.return
é opcional e está implícito no final da função.return
só pode ser usado dentro de uma função.Quero acrescentar que, enquanto estiver sendo originado, não é fácil para
exit
o script de dentro de uma função sem matar o shell. Eu acho que um exemplo é melhor em um script de 'teste'fazendo o seguinte:
test
- e - a concha será fechada.somente
test
terminará e o prompt será exibido.A solução é incluir o potencial procedimento em
(
e)
agora, em ambos os casos, apenas
test
sairá.fonte
(
e)
colocar esse bloco em um sub shell, efetivamente desabilitando o.
comando (origem) como se você tivesse executado o script de teste normalmente, que está em um sub shell. IO script não é executado com.
ousource
então você possui efetivamente 2 sub-shells.A pergunta do OP: Qual é a diferença entre a declaração de retorno e saída nas funções BASH em relação aos códigos de saída?
Por fim, alguns esclarecimentos são necessários:
Na lista de marcadores acima, escolha entre "(x | y)" sempre o primeiro item ou sempre o segundo item para obter instruções sobre funções e retorno ou shells e saída, respectivamente.
O que está claro é que ambos compartilham o uso comum da variável especial $? para passar valores para cima depois que eles terminam.
* Agora, para as formas especiais que $? Pode ser configurado:
Vale a pena notar que $? pode ser atribuído um valor chamando exit em um sub shell, assim:
fonte
exit 259
ecoam como se3
o valor final de saída fosse um único byte.259 % 256 = 3
Primeiro de tudo,
return
é uma palavra-chave eexit
meu amigo é uma função.Dito isto, aqui está uma das explicações mais simples.
return
Retorna um valor de uma função.exit
Ele sai ou abandona o shell atual.fonte
return
é uma palavra-chave. O retorno é muito mais do que apenas códigos de saída, e é por isso que a comparação não é justa.exit
nemreturn
são "palavras-chave", ou, como os festança chamadas manuais eles "palavras reservadas". Também não é uma "função", no sentido de uma função bash. Ambos são comandos internos, no idioma do bash. (Não é uma função C biblioteca padrão chamadoexit()
, e a linguagem de programação C tem uma palavra reservadareturn
, mas aqueles que não deve ser confundido com os comandos bash, apesar de sua semântica são curiosamente similar.)