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
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.
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.
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.
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
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.
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 é:
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.
O modo de shell puro:
[ "${var-}" ] || echo "The variable has not been set"
if set|grep '^somevar=' >/dev/null;then
echo "somevar exists"
else
echo "does not exist"
fi
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
):
declare
. 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.
$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;}
}
$1
contiver o nome de um $array=()
vazio, a chamada a declarar garantiria que obtivéssemos o resultado correto
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
bash que funciona para os tipos escalar e matriz :
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
}
if has_declare name="vars_name" ; then
echo "variable present: vars_name=$vars_name"
fi