Como posso verificar se existe uma variável em uma instrução 'if'?

56

Eu preciso verificar a existência de uma variável em uma instrução if . Algo para o efeito de:

if [ -v $somevar ]
then
    echo "Variable somevar exists!"
else
    echo "Variable somevar does not exist!"

E a pergunta mais próxima disso foi isso , que na verdade não responde à minha pergunta.

    
por Interesting... 25.06.2015 / 18:18

11 respostas

82

No bash moderno (versão 4.2 e acima):

[[ -v name_of_var ]]

De help test :

-v VAR, True if the shell variable VAR is set

    
por 25.06.2015 / 18:36
20

Depende do que você quer dizer com existe .

Uma variável que foi declarada mas não atribuída existe ?

Uma variável de matriz (ou hash) que foi atribuída a uma lista vazia existe ?

Uma variável nameref apontando para uma variável que atualmente não é designada existe ?

Você considera $- , $# , $1 variables? (POSIX não).

Em conchas parecidas com Bourne, a maneira canônica é:

if [ -n "${var+set}" ]; then
  echo '$var was set'
fi

Isso funciona para variáveis escalares e outros parâmetros para informar se uma variável recebeu um valor (vazio ou não, automaticamente, do ambiente, atribuições, read , for ou outro).

Para shells que têm um comando typeset ou declare , isso não reportaria como definir as variáveis que foram declaradas mas não atribuídas exceto em zsh .

Para shells que suportam arrays, exceto yash e zsh que não reportariam como variáveis de array set , a menos que o elemento do indice 0 tenha sido definido.

Para bash (mas não ksh93 nem zsh ), para variáveis do tipo matriz associativa , isso não seria relatado como definido , a menos que seu elemento da chave "0" foi definido.

Para ksh93 e bash , para variáveis do tipo nameref , isso só retorna verdadeiro se a variável referenciada pelo nameref for considerada definida .

Para ksh , zsh e bash , uma abordagem potencialmente melhor poderia ser:

if ((${#var[@]})); then
  echo '$var (or the variable it references for namerefs) or any of its elements for array/hashes has been set'
fi

Para ksh93 , zsh e bash 4.4 ou superior, também há:

if typeset -p var 2> /dev/null | grep -q '^'; then
  echo '$var exists'
fi

Que relatará as variáveis que foram definidas ou declaradas.

    
por 01.12.2015 / 22:32
7

Como mencionado na resposta em SO , aqui está uma maneira de verificar:

if [ -z ${somevar+x} ]; then echo "somevar is unset"; else echo "somevar is set to '$somevar'"; fi

em que $ {somevar + x} é uma expansão de parâmetro que é avaliada como nula se var não estiver definida e substitui a string "x" caso contrário.

Usar -n , como sugerido pela outra resposta, apenas verificará se a variável contém uma string vazia. Não irá verificar a sua existência.

    
por 25.06.2015 / 18:31
2

POSIXly:

! (: "${somevar?}") 2>/dev/null && echo somevar unset

ou você pode deixar seu shell mostrar a mensagem para você:

(: "${somevar?}")
zsh: somevar: parameter not set
    
por 25.06.2015 / 18:41
1
printf ${var+'$var exists!\n'}

... não imprimirá nada quando isso não acontecer. Ou ...

printf $"var does%${var+.}s exist%c\n" \ not !

... dirá de qualquer forma.

você pode usar o valor de retorno de um teste para expandir dinamicamente para a string de formato apropriada para sua condição:

[ "${var+1}" ]
printf $"var does%.$?0s exist%c\n" \ not !

Você também pode fazer printf falhar com base em uma substituição ...

printf $"var does%${var+.}s exist%c\n%.${var+b}d" \
        \ not ! \c >&"$((2${var+-1}))" 2>/dev/null

... que imprime $var does not exist! para stderr e retorna diferente de 0 quando $var não está definido, mas imprime $var does exist! para stdout e retorna 0 quando $var está definido.

    
por 26.06.2015 / 00:32
0

Esta linha simples funciona (e funciona na maioria dos shells POSIX):

${var+"false"} && echo "var is unset"

Ou escrito de uma forma mais longa:

unset var

if ${var+"false"}
then
   echo "var is unset"
fi

A expansão é:

  • Se o var tiver um valor (mesmo nulo), false será substituído
  • Se o var não tiver "nenhum valor", "sem valor" (nulo) será substituído.

A expansão ${var+"false"} se expande para "null" de "false".
Então, "nada" ou o "falso" é executado e o código de saída definido.

Não há necessidade de chamar o comando test ( [ ou [[ ), pois o valor de saída é definido pela (execução) da própria expansão.

    
por 01.12.2015 / 02:11
0

O modo de shell puro:

[ "${var-}" ] || echo "The variable has not been set"
    
por 27.06.2018 / 07:31
-1
if set|grep '^somevar=' >/dev/null;then
    echo "somevar exists"
else
    echo "does not exist"
fi
    
por 25.06.2015 / 19:01
-1

Você não pode usar o comando if para verificar a existência de variáveis declaradas no bash, mas a opção -v existe no bash mais novo, mas não é portátil e você não pode usá-lo em versões antigas do bash . Porque quando você está usando uma variável, se ela não existe, ela nascerá ao mesmo tempo.

Por exemplo Imagine que eu não usei nem atribuí um valor à variável MYTEST , mas quando você está usando o comando echo, não mostra nada! Ou se você estiver usando if [ -z $MYTEST ] , ele retornou valor zero! Ele não retornou outro status de saída, o que indica que essa variável não existe!

Agora você tem duas soluções (sem a opção -v ):

  1. Usando o comando declare .
  2. Usando o comando set .

Por exemplo:

MYTEST=2
set | grep MYTEST
declare | grep MYTEST

Mas, infelizmente, esses comandos também mostram funções carregadas na memória! Você pode usar o comando declare -p | grep -q MYTEST ; echo $? para um resultado mais limpo.

    
por 25.06.2015 / 18:43
-1

Função para verificar se a variável está declarada / não definida

incluindo vazio $array=()


Além da resposta do @Gilles

case " ${!foobar*} " in
  *" foobar "*) echo "foobar is declared";;
  *) echo "foobar is not declared";;
esac

- que eu não encontrei uma maneira de encapsulá-lo dentro de uma função - eu gostaria de adicionar uma versão simples, que é parcialmente baseada em resposta de Richard Hansen , mas também aborda a armadilha que ocorre com um vazio array=() :

# The first parameter needs to be the name of the variable to be checked.
# (See example below)

var_is_declared() {
    { [[ -n ${!1+anything} ]] || declare -p $1 &>/dev/null;}
}

var_is_unset() {
    { [[ -z ${!1+anything} ]] && ! declare -p $1 &>/dev/null;} 
}
  • Ao testar primeiro se a variável é (des) definida, a chamada para declarar pode ser evitada, se não for necessária.
  • Se, entretanto, $1 contiver o nome de um $array=() vazio, a chamada a declarar garantiria que obtivéssemos o resultado correto
  • Nunca há muitos dados passados para / dev / null, pois o declare é chamado apenas se a variável não estiver definida ou estiver vazia.


Com o seguinte código, as funções podem ser testadas:

( # start a subshell to encapsulate functions/vars for easy copy-paste into the terminal
  # do not use this extra parenthesis () in a script!

var_is_declared() {
    { [[ -n ${!1+anything} ]] || declare -p $1 &>/dev/null;}
}

var_is_unset() {
    { [[ -z ${!1+anything} ]] && ! declare -p $1 &>/dev/null;} 
}

:;       echo -n 'a;       '; var_is_declared a && echo "# is declared" || echo "# is not declared"
a=;      echo -n 'a=;      '; var_is_declared a && echo "# is declared" || echo "# is not declared"
a="sd";  echo -n 'a="sd";  '; var_is_declared a && echo "# is declared" || echo "# is not declared"
a=();    echo -n 'a=();    '; var_is_declared a && echo "# is declared" || echo "# is not declared"
a=("");  echo -n 'a=("");  '; var_is_declared a && echo "# is declared" || echo "# is not declared"
unset a; echo -n 'unset a; '; var_is_declared a && echo "# is declared" || echo "# is not declared"
echo ;
:;       echo -n 'a;       '; var_is_unset a && echo "# is unset" || echo "# is not unset"
a=;      echo -n 'a=;      '; var_is_unset a && echo "# is unset" || echo "# is not unset"
a="foo"; echo -n 'a="foo"; '; var_is_unset a && echo "# is unset" || echo "# is not unset"
a=();    echo -n 'a=();    '; var_is_unset a && echo "# is unset" || echo "# is not unset"
a=("");  echo -n 'a=("");  '; var_is_unset a && echo "# is unset" || echo "# is not unset"
unset a; echo -n 'unset a; '; var_is_unset a && echo "# is unset" || echo "# is not unset"
)

O script deve retornar

a;       # is not declared
a=;      # is declared
a="foo"; # is declared
a=();    # is declared
a=("");  # is declared
unset a; # is not declared

a;       # is unset
a=;      # is not unset
a="foo"; # is not unset
a=();    # is not unset
a=("");  # is not unset
unset a; # is unset
    
por 11.03.2016 / 22:48
-1
Função

bash que funciona para os tipos escalar e matriz :

definição

has_declare() { # check if variable is set at all
    local "$@" # inject 'name' argument in local scope
    &>/dev/null declare -p "$name" # return 0 when var is present
}

invocação

if has_declare name="vars_name" ; then
   echo "variable present: vars_name=$vars_name"
fi
    
por 22.10.2017 / 03:36