Testando se uma variável está vazia em um script de shell

27

Eu já vi a seguinte técnica usada muitas vezes em vários shells diferentes, para testar se uma variável está vazia:

if [ "x$1" = "x" ]; then 
    # Variable is empty
fi

Existem vantagens em usar isso em relação aos mais canônicos if [ -z "$1" ]? Poderia ser um problema de portabilidade?

rahmu
fonte

Respostas:

17

Algumas shells históricas implementaram um analisador muito simples que poderia ficar confuso com coisas como [ -n = "" ]onde o primeiro operando se =parece com um operador e analisaria isso como [ -n = ]ou causaria um erro de sintaxe. Em [ "x$1" = x"" ], o xprefixo garante que x"$1"não possa parecer um operador e, portanto, a única maneira pela qual o shell pode analisar esse teste é tratando =como um operador binário.

Todos os shells modernos, e mesmo os shells mais antigos ainda em operação, seguem as regras POSIX que determinam que todas as expressões de teste de até 4 palavras sejam analisadas corretamente. Portanto, [ -z "$1" ]é uma maneira adequada de testar se $1está vazia e [ "$x" = "$y" ]é uma maneira adequada de testar a igualdade de duas variáveis.

Mesmo alguns shells atuais podem se confundir com expressões mais longas, e algumas expressões são realmente ambíguas, portanto, evite usar os operadores -ae -opara construir testes booleanos mais longos, e use chamadas separadas para [os operadores booleanos &&e próprios do shell ||.

Gilles 'SO- parar de ser mau'
fonte
3
Não são apenas conchas históricas . Alguns ksh88 baseados shem alguns escritórios comerciais ainda têm o problema. Veja aqui para detalhes.
Stéphane Chazelas
Esta afirmação está incorreta: [ -z "$1" ]é uma maneira adequada de testar se $1está vazia . sh -c '[ -z "$1" ]' ''; sh -c '[ -z "$1" ]'- ambos retornam 0, mas no segundo caso $1não pode estar vazio porque não existe.
Mikeerv
3

Os testes acima também causarão um erro se você executar com "set -u" ou "set -o nounset"

Uma maneira mais estável de verificar uma variável vazia seria usar a expansão de parâmetros :

MYVAR = $ {MYVAR: - "Valor inválido"}

Este método funciona para o shell bourne tradicional, bem como para o ksh e o bash.

Scott Hoffman
fonte
2
Eu acredito que isso está escrito como -> M = $ {M: - "Bad Value"}
Gyan
0
    function isBlank {
 valueNoSpaces=$(echo "$@" | tr -d ' ')

 if [  "$valueNoSpaces" == null ] || [ -z "$valueNoSpaces" ] 
 then
       echo true ;
 else
       echo ""  ;
 fi
}

#Test
if [ $(isBlank "      ") ] 
then
    echo "isBlank \"      \" : it's blank"
else
    echo " isBlank \"      \": it is not blank"
fi

if [ $(isBlank "abc") ] 

then
    echo "isBlank \"abc\" : it's blank"
else
    echo "isBlank \"abc\" :it is not blank"
fi

if [ $(isBlank null) ] 
then
      echo "isBlank null : it's blank"
else
    echo "isBlank null : it is not blank"
fi

if [ $(isBlank "") ] 
then
    echo "isBlank \"\" : it's blank"
else
    echo "isBlank \"\" : it is not blank"
fi

#Result
isBlank "      " : it's blank

isBlank "abc" :it is not blank

isBlank null : it's blank

isBlank "" : it's blank
aslam mohammed
fonte
3
Oi! Não tenho certeza de como isso responde à pergunta, que pergunta por que usar =versus -z, agora como.
dhag