Como determinar se uma variável bash está vazia?

726

Qual é a melhor maneira de determinar se uma variável no bash está vazia ("")?

Ouvi dizer que é recomendável que eu faça if [ "x$variable" = "x" ]

Esse é o caminho correto ? (deve haver algo mais simples)

    
por Brent 12.05.2009 / 19:54

12 respostas

991

Isso retornará verdadeiro se uma variável não estiver definida ou definida para a cadeia vazia ("").

if [ -z "$VAR" ];
    
por 12.05.2009 / 20:06
232

No Bash, quando você não está preocupado com a portabilidade para shells que não suportam, você deve sempre usar a sintaxe de colchetes duplos:

Qualquer um dos seguintes itens:

if [[ -z $variable ]]
if [[ -z "$variable" ]]
if [[ ! $variable ]]
if [[ ! "$variable" ]]

No Bash, usando colchetes duplos, as aspas não são necessárias. Você pode simplificar o teste para uma variável que contém um valor para:

if [[ $variable ]]

Esta sintaxe é compatível com o ksh (pelo menos o ksh93, de qualquer forma). Ele não funciona em shells POSIX ou Bourne mais antigos, como sh ou dash.

Veja minha resposta aqui e BashFAQ / 031 para mais informações sobre as diferenças entre colchetes duplos e simples.

Você pode testar para ver se uma variável é especificamente não definida (como distinta de uma string vazia):

if [[ -z ${variable+x} ]]

onde o "x" é arbitrário.

Se você quiser saber se uma variável é nula, mas não está definida:

if [[ -z $variable && ${variable+x} ]]
    
por 25.02.2012 / 04:37
211

Uma variável no bash (e qualquer shell compatível com POSIX) pode estar em um dos três estados:

  • não definido
  • definido para a string vazia
  • definido para uma string não vazia

Na maioria das vezes, você só precisa saber se uma variável está definida como uma string não vazia, mas ocasionalmente é importante distinguir entre não definida e definida como a string vazia.

Seguem-se exemplos de como você pode testar as várias possibilidades, e funciona em bash ou qualquer shell compatível com POSIX:

if [ -z "${VAR}" ]; then
    echo "VAR is unset or set to the empty string"
fi
if [ -z "${VAR+set}" ]; then
    echo "VAR is unset"
fi
if [ -z "${VAR-unset}" ]; then
    echo "VAR is set to the empty string"
fi
if [ -n "${VAR}" ]; then
    echo "VAR is set to a non-empty string"
fi
if [ -n "${VAR+set}" ]; then
    echo "VAR is set, possibly to the empty string"
fi
if [ -n "${VAR-unset}" ]; then
    echo "VAR is either unset or set to a non-empty string"
fi

Aqui está a mesma coisa, mas em forma de tabela útil:

                        +-------+-------+-----------+
                VAR is: | unset | empty | non-empty |
+-----------------------+-------+-------+-----------+
| [ -z "${VAR}" ]       | true  | true  | false     |
| [ -z "${VAR+set}" ]   | true  | false | false     |
| [ -z "${VAR-unset}" ] | false | true  | false     |
| [ -n "${VAR}" ]       | false | false | true      |
| [ -n "${VAR+set}" ]   | false | true  | true      |
| [ -n "${VAR-unset}" ] | true  | false | true      |
+-----------------------+-------+-------+-----------+

A construção ${VAR+foo} se expande para a sequência vazia se VAR não estiver definido ou para foo se VAR estiver definido como qualquer coisa (incluindo a sequência vazia).

A construção ${VAR-foo} se expande para o valor de VAR se definido (incluindo a cadeia vazia) e foo se não definido. Isso é útil para fornecer padrões substituíveis pelo usuário (por exemplo, ${COLOR-red} diz usar red , a menos que a variável COLOR tenha sido definida como algo).

O motivo pelo qual [ x"${VAR}" = x ] é frequentemente recomendado para testar se uma variável não está definida ou está definida para a cadeia vazia é porque algumas implementações do comando [ (também conhecido como test ) estão com bugs. Se VAR estiver definido como algo como -n , algumas implementações farão a coisa errada quando receber [ "${VAR}" = "" ] , porque o primeiro argumento para [ é erroneamente interpretado como o operador -n , não uma cadeia de caracteres.

    
por 24.04.2012 / 22:39
37

-z é o melhor caminho.

Outra opção que usei foi definir uma variável, mas ela pode ser substituída por outra variável, por exemplo

export PORT=${MY_PORT:-5432}

Se a variável $MY_PORT estiver vazia, então PORT será definido como 5432, caso contrário, PORT será definido com o valor de MY_PORT . Observe que a sintaxe inclui os dois pontos e o traço.

    
por 11.06.2009 / 15:19
24

Se você estiver interessado em distinguir os casos de status set-empty versus unset, veja a opção -u do bash:

$ set -u
$ echo $BAR
bash: BAR: unbound variable
$ [ -z "$BAR" ] && echo true
bash: BAR: unbound variable
$ BAR=""
$ echo $BAR

$ [ -z "$BAR" ] && echo true
true
    
por 12.05.2009 / 20:21
8

Uma alternativa que eu vi para [ -z "$foo" ] é a seguinte, mas não sei por que as pessoas usam esse método, alguém sabe?

[ "x${foo}" = "x" ]

De qualquer forma, se você não estiver permitindo variáveis não definidas (seja por set -u ou set -o nounset ), você terá problemas com esses dois métodos. Há uma solução simples para isso:

[ -z "${foo:-}" ]

Observação: isso deixará sua variável indefinida

    
por 20.10.2011 / 05:58
6

A pergunta pergunta como verificar se uma variável é uma string vazia e as melhores respostas já foram dadas para isso.
Mas eu desembarquei aqui depois de um período passado de programação em php e o que eu estava realmente procurando era um cheque como a função vazia em php trabalhando em um shell bash. Depois de ler as respostas, percebi que não estava pensando corretamente no bash, mas de qualquer forma, naquele momento, uma função como vazio no php teria sido muito útil no meu código bash. Como acho que isso pode acontecer com os outros, decidi converter a função vazia do php no bash

De acordo com o manual do PHP :
uma variável é considerada vazia se não for existe ou se o seu valor é um dos seguintes:

  • "" (uma string vazia)
  •     
  • 0 (0 como um inteiro)
  •     
  • 0,0 (0 como float)
  •     
  • "0" (0 como uma string)
  •     
  • uma matriz vazia
  •     
  • uma variável declarada, mas sem um valor

É claro que os casos null e false não podem ser convertidos no bash, então eles são omitidos.

function empty
{
    local var="$1"

    # Return true if:
    # 1.    var is a null string ("" as empty string)
    # 2.    a non set variable is passed
    # 3.    a declared variable or array but without a value is passed
    # 4.    an empty array is passed
    if test -z "$var"
    then
        [[ $( echo "1" ) ]]
        return

    # Return true if var is zero (0 as an integer or "0" as a string)
    elif [ "$var" == 0 2> /dev/null ]
    then
        [[ $( echo "1" ) ]]
        return

    # Return true if var is 0.0 (0 as a float)
    elif [ "$var" == 0.0 2> /dev/null ]
    then
        [[ $( echo "1" ) ]]
        return
    fi

    [[ $( echo "" ) ]]
}



Exemplo de uso:

if empty "${var}"
    then
        echo "empty"
    else
        echo "not empty"
fi



Demo:
o seguinte snippet:

#!/bin/bash

vars=(
    ""
    0
    0.0
    "0"
    1
    "string"
    " "
)

for (( i=0; i<${#vars[@]}; i++ ))
do
    var="${vars[$i]}"

    if empty "${var}"
        then
            what="empty"
        else
            what="not empty"
    fi
    echo "VAR \"$var\" is $what"
done

exit

saídas:

VAR "" is empty
VAR "0" is empty
VAR "0.0" is empty
VAR "0" is empty
VAR "1" is not empty
VAR "string" is not empty
VAR " " is not empty
Tendo dito que em uma lógica bash as verificações em zero nesta função podem causar problemas colaterais, qualquer um usando essa função deve avaliar esse risco e talvez decidir cortar essas verificações deixando apenas a primeira.

strong>

    
por 31.08.2012 / 22:11
5

todo if-then e -z são desnecessários.

[ "$foo" ] && echo "foo is not empty"
[ "$foo" ] || echo "foo is indeed empty"
    
por 26.01.2010 / 15:02
4

Isso é verdadeiro exatamente quando $ FOO está definido e vazio:

[ "${FOO+x}" = x ] && [ -z "$FOO" ]
    
por 20.05.2010 / 22:52
4

Pessoalmente, prefira uma maneira mais clara de verificar:

if [ "${VARIABLE}" == "" ]; then
  echo VARIABLE is empty
else
  echo VARIABLE is not empty
fi
    
por 09.12.2011 / 16:15
3

extensão oneliner da solução duffbeer703 :

#! /bin/bash
[ -z "$1" ] || some_command_that_needs_$1_parameter
    
por 31.08.2012 / 13:34
3

Meus 5 centavos: também há uma sintaxe mais curta que if ... , desta vez:

VALUE="${1?"Usage: $0 value"}"

Esta linha irá definir VALOR se um argumento tiver sido fornecido e imprimirá uma mensagem de erro anexada ao número da linha de script em caso de erro (e terminará a execução do script).

Outro exemplo pode ser encontrado no guia abs (procure por «Exemplo 10-7 »).

    
por 09.11.2015 / 17:46