Estou trabalhando em um script altamente portátil que os usuários deverão usar em seus shells, forçando-me a usar scripts POSIX.
Existem muitas funções úteis no script, mas uma delas é especial, pois retorna
true
oufalse
status para a função de chamada.
Agora, eu costumava usar return 0
em casos como este. Mas parece muito mais legível true
ou false
for return 1
, respectivamente, também funciona.
A questão é se funcionam da mesma maneira ou se há alguma diferença. Obrigado.
true
é portátil, mas não retorna por si só.return true
não é portátil e também não funciona de maneira confiável.Se você tiver uma função como esta:
Então sim, ele retornará portávelmente da função com status de saída zero. Ao cair do final, o status de saída do último comando é retornado como o status de saída da função.
Mas é claro que isso não retorna com um status verdadeiro, já que o
true
meio por si só não afeta o fluxo de controle.Mas você poderia adicionar um retorno explícito, pois
return
sem argumentos também usa o status de saída do último comando :Agora, se você tentasse
return true
, poderia parecer que faria o que você queria em alguns shells, mas no final provavelmente não faz. Pelo menos no zsh, parece considerar o argumento como uma expressão aritmética; portanto,return true
usaria o valor da variáveltrue
ou zero por padrão, se não estiver definido.Se você puder fazer com
true
que seja sempre definido como0
, efalse
seja definido como1
, e confiar que os usuários da sua biblioteca de scripts não mexerão com eles, então você poderá usarreturn true
andreturn false
no zsh, oureturn "$true"
ereturn "$false"
em um shell padrão. Eu não recomendaria isso com esses nomes, mas talvez algo parecidotrue_return_value
oufalse_return_value
pudesse ser usado.Caso contrário, você poderia usar
true; return
andfalse; return
em um shell padrão, mas não tenho certeza se isso é mais legível quereturn 0
andreturn 1
. O fato de o valor de retorno verdadeiro ser zero deve ser familiar aos programadores de shell em qualquer caso.true
efalse
não são valores booleanos válidos portáveis.Por exemplo, um script de shell simples
Se executarmos isso em diferentes shells:
(O último shell é pdksh 5.2.14)
No entanto
return 0
, é portátilTambém podemos ver um retorno se 0 for contado como verdadeiro, então funciona
&&
.Agora podemos meio que trapacear.
O que isso faz é chamar o
true
comando... e então usar o fato de que o código de retorno de uma função sem explícitoreturn
é o retorno do último comando executado.Então, embora isso funcione , não é tão legível, porque não há nada explícito
return
e você está contando com um comportamento implícito.Aqui está o que o POSIX tem a dizer sobre isso :
Então:
você pode usar
return
para retornar de scripts de origem (script de ponto), não apenas de funções.Você pode passar 0 ou 1 argumento (sem opção,
--
pode nem ser aceito ), mas deve ser um número inteiro decimal sem sinal (0
,1
,2
... nottrue
,0x1
,-1
,+1
, pouco claro e na prática não portátil para010
o qual poderia ser visto como um número octal, não decimal e na prática é como em zsh quando em emulação sh)porque
return
sem argumentos retorna com o status do comando anterior,{ true; return; }
pode ser uma forma de retornar com status de saída de sucesso. Cuidado, porém, isso{ false; return; }
retornaria com um status de não saída, mas o status de saída retornadofalse
não é especificado (na prática, nunca vi nenhuma implementação que usasse algo diferente de1
) efalse
pode sair do shell (ou subshell) se aerrexit
opção está habilitado (pode ser contornado com{ false || return; }
). Não está claro sereturn $(true)
oureturn $(false)
deveria funcionar. Na prática, não funciona no dash nem no mksh, por exemplo, portanto não é portátil.não está perfeitamente claro o que o shell não está executando uma função ou script de ponto significa exatamente. Alguns têm interpretado isso como significando que o uso
return
de um subshell, mesmo quando esse subshell é executado a partir de uma função ou script de ponto ou o corpo da função (como emf() (return 1)
), não é especificado. Na prática, porém, acho quereturn
nesses casos age comoexit
. Ele sai/retorna do subshell atual, mas não da função/script de ponto envolvente.Em qualquer caso, para retornar de uma função/ponto-script, isso deve ser feito fora de um subshell se esse subshell não for o último comando na função/ponto-script, tendo em mente que o que constitui um subshell varia entre shell . Por exemplo em:
the
return
retornaria da função em ksh ou zsh, mas não em bash (a menos que alastpipe
opção esteja definida) ou dash, mksh porque nesses, todos os componentes do pipe, mesmo o último executado em um subshell (conforme permitido pelo POSIX). Então você precisaria contornar isso com algo como:Forçar um subshell e usá-lo
exit
dentro dele o tornaria claramente POSIX e se comportaria de forma consistente entre shells (e também mais claro que a$var
atribuição de variável porread
pode não sobreviver ao pipeline):(em todos esses
return
/exit
retornaria com o status de saída de falharead
; você pode alterar paraexit 1
/return 1
para fornecer um valor específico de status de saída de falha)observe que o comportamento de
! return
or! return 1
não é portátil (não é tão útil parareturn
, mas seria mais útil se fosse portátil para! break
interromper loops com status de saída de falha).Em qualquer caso, os comandos
true
efalse
não fazem com que a função/script de ponto envolvente retorne, exceto conforme já observado para o caso especial em que aerrexit
opção está definida (e seu efeito não é cancelado de uma forma ou de outra), caso em que falha comandos incluindofalse
a saída do processo shell (não necessariamente/apenas a função/script de ponto envolvente), eles são comandos comuns, geralmente integrados, mas não integrados especiais e muito menos operadores de fluxo de controle contrários areturn
/break
/continue
...Para tornar seu código mais legível, você pode optar por definir variáveis para o status de saída bem-sucedida e para um status de saída com falha, como:
E use
return "$true"
orreturn "$false"
ou mesmo comexit
, que em zsh pode ser simplificadoreturn $true
ou até mesmoreturn true
Porém, tenha cuidado, pois em expressões aritméticas, o significado é invertido, 0 significando falso e qualquer outra coisa verdadeira como em C. Portanto, com esses valores dessas variáveis
while (( true ))
(em shells do tipo Korn) não funcionariam como esperado, então você pode preferir nomeá-los variáveisstatus_ok
,status_failure
em vez deok
/failure
.