o uso de set -u não funciona conforme o esperado

Estou aprendendo a usar com eficiência diferentes set opções em meu script e encontrei set -u que parece ser perfeito para sair do meu script se uma variável não for configurada corretamente (por exemplo, excluir usuários). De acordo com a página man , set -u e set -e faz o seguinte …

-e Exit immediately if a command exits with a non-zero status. -u Treat unset variables as an error when substituting. 

Criei um script de teste para testar esta funcionalidade, mas não parece estar funcionando como esperado . Talvez alguém pudesse explicar melhor meu problema para mim e onde estou interpretando mal? O script de teste está abaixo. Obrigado.

set -e set -u testing="This works" echo $? echo ${testing} testing2= echo $? echo ${testing2} testing3="This should not appear" echo $? echo ${testing3} 

Espero que o script exiba 0 e “Isso funciona” e falha porque ${testing2} é não definido.

Em vez disso, sou exibido 0 e “Isso funciona” , seguido por 0 e então 0 Isso não deve aparecer

Alguém pode fornecer algum conhecimento? Obrigado.

Comentários

  • Então, continuação … há alguma maneira de tornar ilegal a configuração de uma variável como string nula / gerar um erro? Eu ' suponho que não.

Resposta

De ” man Bash “:

Um parâmetro é definido se tiver sido atribuído um valor. A string nula é um valor válido. Depois que uma variável é definida, ela pode ser removida apenas usando o comando interno unset.

Quando você faz testing2= você está definindo a variável como string nula.

Altere para unset testing2 e tente novamente.


O set -e não ajuda neste caso, pois uma atribuição nunca tem um código de saída 1. Tente isso para ver se o último comando executado (a atribuição) tem um código de saída 0, ou leia esta pergunta :

$ false; a=""; echo $? 0 

E também acredito que o uso de set -e é mais um problema do que uma solução.

O que pode gerar um erro com o uso de variáveis não definidas é set -u:

#!/bin/bash set -u testing="This works" echo ${testing} unset testing2 echo ${testing2} testing3="This should not appear" echo ${testing3} 

Irá gerar:

$ ./script.sh This works ./script.sh: line 9: testing2: unbound variable 

Resposta

testing2= define a variável testing2 como uma string vazia; a variável realmente está definida .

No entanto, se você executasse echo $testing99 em um shell Bash interativo (sem definir errexit, ou seja, set -e), você obteria um erro:

bash: testing99: unbound variable 

À parte

Ao testar scripts agora, descobri que um shell interativo nem sempre sai ao tentar expandir uma variável que não foi definida enquanto um shell não interativo (executando um script de shell) sempre sai de . De acordo com a página do manual POSIX para set:

-u O shell deve escrever uma mensagem de erro padrão quando tenta expandir uma variável que não está configurada e sai imediatamente. Um shell interativo não deve sair.

Um shell Bash interativo não sairá a menos que errexit tenha também foi definido. Por outro lado, um shell de traço interativo não sairá – mesmo se set -e tiver sido executado anteriormente.

Comentários

  • Se o traço não sair com set -e; set -u; não definido aa; echo $ aa, então o traço está errado.
  • @schily Quando percebi isso pela primeira vez, percebi que os autores do traço sabiam melhor do que eu e que pode ter havido alguma ambiguidade nas especificações POSIX, mas tendo verificado pubs.opengroup.org/onlinepubs/9699919799/utilities/… , concordo que parece um bug, certo.
  • Há uma regra simples: quando o Korn Shell e o Bourne Shell concordam e outra implementação do shell tem um desvio, o outro shell se comporta incorretamente.

Deixe uma resposta

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