Para las versiones de Bash anteriores a "GNU bash, Version 4.2", ¿hay alternativas equivalentes para la -v
opción del test
comando? Por ejemplo:
shopt -os nounset
test -v foobar && echo foo || echo bar
# Output: bar
foobar=
test -v foobar && echo foo || echo bar
# Output: foo
-v
no es una opcióntest
, sino un operador para expresiones condicionales.option
a un comandotest -v
, anoperator
a ayconditional expression
aunary test primary
para[ ]
. No mezcles el idioma inglés con las definiciones de shell.Respuestas:
Portátil para todos los proyectiles POSIX:
Haga eso
${foobar:+1}
si desea tratar defoobar
la misma manera si está vacío o no está definido. También puede usar${foobar-}
para obtener una cadena vacía cuandofoobar
no está definida y el valor de lofoobar
contrario (o poner cualquier otro valor predeterminado después de-
).En ksh, si
foobar
se declara pero no se define, como entypeset -a foobar
, entonces${foobar+1}
expande a la cadena vacía.Zsh no tiene variables declaradas pero no establecidas:
typeset -a foobar
crea una matriz vacía.En bash, las matrices se comportan de una manera diferente y sorprendente.
${a+1}
solo se expande a1
sia
es una matriz no vacía, por ejemploEl mismo principio se aplica a las matrices asociativas: las variables de matriz se tratan como se define si tienen un conjunto de índices no vacío.
Una forma diferente y específica de bash de probar si se ha definido una variable de cualquier tipo es verificar si está incluida en la lista . Esto informa que las matrices vacías están definidas, a diferencia , pero informa que las variables declaradas pero no asignadas ( ) no están definidas.
${!PREFIX*}
${foobar+1}
unset foobar; typeset -a foobar
Esto es equivalente a probar el valor de retorno de
typeset -p foobar
odeclare -p foobar
, excepto quetypeset -p foobar
falla en variables declaradas pero no asignadas.En bash, como en ksh,
set -o nounset; typeset -a foobar; echo $foobar
desencadena un error en el intento de expandir la variable indefinidafoobar
. A diferencia de ksh,set -o nounset; foobar=(); echo $foobar
(oecho "${foobar[@]}"
) también desencadena un error.Tenga en cuenta que en todas las situaciones descritas aquí, se
${foobar+1}
expande a la cadena vacía si y solo si$foobar
causaría un error debajoset -o nounset
.fuente
echo "${foobar:+1}"
no se imprime1
sideclare -a foobar
se emitió anteriormente y, por lo tanto,foobar
es una matriz indexada.declare -p foobar
informa correctamentedeclare -a foobar='()'
. ¿"${foobar:+1}"
Solo funciona para variables sin matriz?${foobar+1}
(sin el:
, invertí dos ejemplos en mi respuesta original) es correcto para las matrices en bash si su definición de "definido" es "$foobar
funcionaría enset -o nounset
". Si tu definición es diferente, bash es un poco raro. Ver mi respuesta actualizada.0
índice ni una clave se definen como verdaderosa=()
,${a+1}
correctamente no devuelve nada.defined
operador.Test
podría hacer eso; no puede ser difícil ( um ...)Para resumir con la respuesta de Gilles, inventé mis siguientes reglas:
[[ -v foobar ]]
para variables en la versión Bash> = 4.2.declare -p foobar &>/dev/null
para variables de matriz en la versión Bash <4.2.(( ${foo[0]+1} ))
o(( ${bar[foo]+1} ))
para subíndices de arrays indexados (-a
) y codificados-A
(declare
), respectivamente. Las opciones 1 y 2 no funcionan aquí.fuente
Utilizo la misma técnica para todas las variables en bash, y funciona, por ejemplo:
salidas:
mientras que
salidas:
fuente
foobar=""
luego informaré esofoobar is unset
. No, espera, lo retiro. Realmente solo prueba si el primer elemento está vacío o no, por lo que parece ser una buena idea si sabe que la variable NO es una matriz, y solo le importa el vacío, no la definición.