Veja os exemplos a seguir e suas saídas nos shells POSIX:
false;echo $?
oufalse || echo 1
:1
false;foo="bar";echo $?
oufoo="bar" && echo 0
:0
foo=$(false);echo $?
oufoo=$(false) || echo 1
:1
foo=$(true);echo $?
oufoo=$(true) && echo 0
:0
Conforme mencionado pela resposta mais votada em /programming/6834487/what-is-the-variable-in-shell-scripting :
$?
é usado para encontrar o valor de retorno do último comando executado.
Isso provavelmente é um pouco enganador nesse caso, então vamos obter a definição POSIX, que também é citada em um post desse segmento:
? Expande para o status de saída decimal do pipeline mais recente (consulte Pipelines).
Portanto, parece que uma atribuição em si conta como um comando (ou melhor, como uma parte do pipeline) com um valor de saída zero, mas que se aplica antes do lado direito da atribuição (por exemplo, a substituição de comando chama nos meus exemplos aqui).
Vejo como esse comportamento faz sentido do ponto de vista prático, mas me parece um pouco incomum que a tarefa em si contaria nessa ordem. Talvez para deixar mais claro por que isso é estranho para mim, vamos assumir que a tarefa era uma função:
ASSIGNMENT( VARIABLE, VALUE )
então foo="bar"
seria
ASSIGNMENT( "foo", "bar" )
e foo=$(false)
seria algo como
ASSIGNMENT( "foo", EXECUTE( "false" ) )
o que significa que as EXECUTE
execuções são executadas primeiro e somente depois, ASSIGNMENT
mas ainda é o EXECUTE
status que importa aqui.
Estou correto na minha avaliação ou estou entendendo errado / faltando alguma coisa? Essas são as razões certas para eu ver esse comportamento como "estranho"?
false;foo="bar";echo $?
sempre retorna 0 quando o último comando real executado foifalse
?" É basicamente que as atribuições se comportam de maneira especial quando se trata de códigos de saída. Seu código de saída é sempre 0, exceto quando não é por causa de algo que foi executado como parte do lado direito da tarefa.Respostas:
O status de saída para atribuições é estranho . A maneira mais óbvia de uma atribuição falhar é se a variável de destino estiver marcada
readonly
.Observe que nem os caminhos verdadeiro nem falso da instrução if foram utilizados; a falha na atribuição parou a execução de toda a instrução. o bash no modo POSIX e o ksh93 e o zsh abortam um script se uma atribuição falhar.
Para citar o padrão POSIX sobre isso :
Essa é exatamente a parte da gramática de shell envolvida no
que vem de um
simple_command
(comando_ simples → cmd_prefix → ASSIGNMENT_WORD). Portanto, se uma atribuição for bem-sucedida, o status de saída será zero, a menos que a substituição do comando esteja envolvida; nesse caso, o status de saída será o status do último. Se a atribuição falhar, o status de saída será diferente de zero, mas talvez você não possa obtê-lo.fonte
Você diz,
Essa não é uma maneira terrível de encarar. Mas é uma pequena simplificação excessiva. O status geral de retorno de
é o status de saída de . A atribuição que ocorre após a atribuição não define o status geral da saída como 0.cmd4
E=
D=
Além disso, como o icarus aponta , as variáveis podem ser definidas como somente leitura. Considere a seguinte variação no exemplo do icarus:
Mesmo sendo
A
somente leitura, o bash executa a substituição do comando à direita deA=
- e depois anula o comando porqueA
é somente leitura. Isso contradiz ainda mais a sua interpretação de que o valor de saída da atribuição se aplica antes do lado direito da atribuição.fonte