Para versões do Bash anteriores ao "GNU bash, versão 4.2", existem alternativas equivalentes para a -v
opção do test
comando? Por exemplo:
shopt -os nounset
test -v foobar && echo foo || echo bar
# Output: bar
foobar=
test -v foobar && echo foo || echo bar
# Output: foo
-v
não é uma opçãotest
, mas um operador para expressões condicionais.option
para um comandotest -v
, umoperator
para umconditional expression
e umunary test primary
para[ ]
. Não misture o idioma inglês com as definições de shell.Respostas:
Portátil para todos os invólucros POSIX:
Faça isso
${foobar:+1}
se quiser tratarfoobar
da mesma maneira, esteja vazio ou não definido. Você também pode usar${foobar-}
para obter uma sequência vazia quandofoobar
indefinida e o valor defoobar
outra forma (ou colocar qualquer outro valor padrão depois da-
).Em ksh, se
foobar
for declarado, mas não definido, como emtypeset -a foobar
, será${foobar+1}
expandido para a sequência vazia.O Zsh não possui variáveis declaradas, mas não definidas:
typeset -a foobar
cria uma matriz vazia.No bash, as matrizes se comportam de uma maneira diferente e surpreendente.
${a+1}
somente se expande para1
sea
for uma matriz não vazia, por exemploO mesmo princípio se aplica a matrizes associativas: variáveis de matriz são tratadas como definidas se tiverem um conjunto de índices não vazio.
Uma maneira diferente e específica do bash de testar se uma variável de qualquer tipo foi definida é verificar se ela está listada . Isso relata matrizes vazias conforme definido, diferentemente , mas relata variáveis declaradas mas não atribuídas ( ) como indefinidas.
${!PREFIX*}
${foobar+1}
unset foobar; typeset -a foobar
Isso é equivalente a testar o valor de retorno de
typeset -p foobar
ordeclare -p foobar
, exceto quetypeset -p foobar
falha em variáveis declaradas, mas não atribuídas.No bash, como no ksh,
set -o nounset; typeset -a foobar; echo $foobar
dispara um erro na tentativa de expandir a variável indefinidafoobar
. Ao contrário do ksh,set -o nounset; foobar=(); echo $foobar
(ouecho "${foobar[@]}"
) também dispara um erro.Observe que em todas as situações descritas aqui, se
${foobar+1}
expande para a cadeia vazia se e somente se$foobar
causaria um erro emset -o nounset
.fonte
echo "${foobar:+1}"
não é impressa1
se tiverdeclare -a foobar
sido emitida anteriormente e, portanto,foobar
é uma matriz indexada.declare -p foobar
relatórios corretamentedeclare -a foobar='()'
. Funciona"${foobar:+1}"
apenas para variáveis que não são de matriz?${foobar+1}
(sem o:
, inverti dois exemplos na minha resposta original) está correto para matrizes no bash se sua definição de "definido" for "$foobar
funcionaria sobset -o nounset
". Se sua definição for diferente, o bash é um pouco estranho. Veja minha resposta atualizada.0
índice nem uma chave são definidos como é verdadea=()
,${a+1}
retornam corretamente nada.defined
operador.Test
poderia fazer isso; não pode ser difícil ( hum ....)Para resumir a resposta de Gilles, criei as seguintes regras:
[[ -v foobar ]]
para variáveis na versão Bash> = 4.2.declare -p foobar &>/dev/null
para variáveis de matriz na versão Bash <4.2.(( ${foo[0]+1} ))
ou(( ${bar[foo]+1} ))
para subscritos de matrizes indexadas (-a
) e com chave (-A
) (declare
), respectivamente. As opções 1 e 2 não funcionam aqui.fonte
Eu uso a mesma técnica para todas as variáveis no bash e funciona, por exemplo:
saídas:
enquanto
saídas:
fonte
foobar=""
relatará issofoobar is unset
. Não, espere, eu retiro isso. Realmente apenas testa se o primeiro elemento está vazio ou não, então parece ser apenas uma boa idéia se você souber que a variável NÃO é uma matriz e se preocupa apenas com o vazio, não com a definição.