Para las versiones de Bash anteriores a "GNU bash, Version 4.2", ¿hay alternativas equivalentes para la -vopción del testcomando? Por ejemplo:
shopt -os nounset
test -v foobar && echo foo || echo bar
# Output: bar
foobar=
test -v foobar && echo foo || echo bar
# Output: foo
                
-vno es una opcióntest, sino un operador para expresiones condicionales.optiona un comandotest -v, anoperatora ayconditional expressionaunary test primarypara[ ]. 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 defoobarla misma manera si está vacío o no está definido. También puede usar${foobar-}para obtener una cadena vacía cuandofoobarno está definida y el valor de lofoobarcontrario (o poner cualquier otro valor predeterminado después de-).En ksh, si
foobarse 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 foobarcrea una matriz vacía.En bash, las matrices se comportan de una manera diferente y sorprendente.
${a+1}solo se expande a1siaes 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 foobarEsto es equivalente a probar el valor de retorno de
typeset -p foobarodeclare -p foobar, excepto quetypeset -p foobarfalla en variables declaradas pero no asignadas.En bash, como en ksh,
set -o nounset; typeset -a foobar; echo $foobardesencadena 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$foobarcausaría un error debajoset -o nounset.fuente
echo "${foobar:+1}"no se imprime1sideclare -a foobarse emitió anteriormente y, por lo tanto,foobares una matriz indexada.declare -p foobarinforma 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 "$foobarfuncionarí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.definedoperador.Testpodrí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/nullpara 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.