Por que [[-z]] e [[-v]] possuem sintaxe diferente?

7

Se eu quiser executar alguns comandos, dadas variáveis não estão definidas, estou usando:

if [[ -z "$a" || -z "$v" ]]
then
  echo "a or b are not set"
fi

Ainda a mesma sintaxe não funciona com -v , eu tenho que usar:

if [[ -v a && -v b ]]
then
  echo "a & b are set"
fi

Qual é a história por trás disso? Eu não entendo porque a sintaxe não seria a mesma. Eu li que -v é uma adição recente ao bash (4.2) ?

    
por Philip Kirkbride 06.10.2017 / 16:51

2 respostas

20

Operadores de teste -v e -z simplesmente não são iguais.

O operador -z informa se uma string está vazia. Portanto, é verdade que [[ -z "$a" ]] dará uma boa aproximação de "variável a is unset", mas não perfeito:

  • a expressão produzirá true se a for definido como a string vazia em vez de desanexar;

  • o script anexo falhará se a não estiver definido e a opção nounset está ativado.

Por outro lado, -v a será exatamente "variável a definida", mesmo em casos de borda. Deve ficar claro que passar $a em vez de a para -v não estaria certo, pois expandiria essa possibilidade - não definida variável antes que o operador de teste a veja; então tem que ser parte de essa tarefa do operador para inspecionar essa variável, apontada pelo seu nome, e diga se está definido.

    
por 06.10.2017 / 17:05
7

Há uma diferença no significado de -z e -v :

echo Empty:
x=""  # Same with x=
[[ -z $x ]] && echo z
[[ -v  x ]] && echo v
unset x

echo Unset
[[ -z $x ]] && echo z
[[ -v  x ]] && echo v

Ao usar -z , não é possível distinguir uma variável que recebeu um valor vazio de uma variável que não recebeu nenhum valor.

Além disso, [[ -z $x ]] ainda é sensível a set -u , enquanto [[ -v x ]] não é.

    
por 06.10.2017 / 17:05