El siguiente código sale con un error de variable independiente. ¿Cómo solucionar esto, sin dejar de usar la set -o
opción de conjunto de nombres?
#!/bin/bash
set -o nounset
if [ ! -z ${WHATEVER} ];
then echo "yo"
fi
echo "whatever"
Respuestas:
#!/bin/bash
set -o nounset
VALUE=${WHATEVER:-}
if [ ! -z ${VALUE} ];
then echo "yo"
fi
echo "whatever"
En este caso, VALUE
termina siendo una cadena vacía si WHATEVER
no se establece. Estamos usando la {parameter:-word}
expansión, que puede buscar en man bash
"Expansión de parámetros".
:-
comprueba si la variable no está definida o está vacía. Si desea comprobar únicamente si se trata de desarmar, utilice -
: VALUE=${WHATEVER-}
. Además, una forma más legible de comprobar si una variable está vacía:if [ "${WHATEVER+defined}" = defined ]; then echo defined; else echo undefined; fi
$WHATEVER
solo contiene espacios en blanco: vea mi respuesta.
! -z
" en lugar de solo " -n
"?
Debe citar las variables si desea obtener el resultado que espera:
check() {
if [ -n "${WHATEVER-}" ]
then
echo 'not empty'
elif [ "${WHATEVER+defined}" = defined ]
then
echo 'empty but defined'
else
echo 'unset'
fi
}
Prueba:
$ unset WHATEVER
$ check
unset
$ WHATEVER=
$ check
empty but defined
$ WHATEVER=' '
$ check
not empty
"info bash"
, "${WHATEVER-}"
debe tener un ":"
(colon) antes de la "-"
(guión) como: "${WHATEVER:-}"
, y "${WHATEVER+defined}"
debe tener un colon antes de la "+"
(más) como: "${WHATEVER:+defined}"
. Para mí, funciona de cualquier manera, con o sin los dos puntos. En algunas versiones de 'nix probablemente no funcionará sin incluir los dos puntos, por lo que probablemente debería agregarse.
-
, +
, :+
, y :-
son compatibles. Los primeros detectan si la variable está configurada y los segundos detectan si está configurada o vacía . De man bash
: "Omitir los dos puntos da como resultado una prueba solo para un parámetro que no está configurado".
¿Qué tal un delineador?
[ -z "${VAR:-}" ] && echo "VAR is not set or is empty" || echo "VAR is set to $VAR"
-z
comprueba tanto la variable vacía como la no definida
-z
solo comprueba si el siguiente parámetro está vacío. -z
es solo un argumento del [
comando. La expansión variable ocurre antes de que [ -z
pueda hacer nada.
Supuestos:
$ echo $SHELL
/bin/bash
$ /bin/bash --version | head -1
GNU bash, version 4.1.2(1)-release (x86_64-redhat-linux-gnu)
$ set -o nounset
Si desea que un script no interactivo imprima un error y salga si una variable es nula o no está establecida:
$ [[ "${HOME:?}" ]]
$ [[ "${IAMUNBOUND:?}" ]]
bash: IAMUNBOUND: parameter null or not set
$ IAMNULL=""
$ [[ "${IAMNULL:?}" ]]
bash: IAMNULL: parameter null or not set
Si no desea que se cierre el script:
$ [[ "${HOME:-}" ]] || echo "Parameter null or not set."
$ [[ "${IAMUNBOUND:-}" ]] || echo "Parameter null or not set."
Parameter null or not set.
$ IAMNULL=""
$ [[ "${IAMUNNULL:-}" ]] || echo "Parameter null or not set."
Parameter null or not set.
Incluso puedes usar [
y en ]
lugar de[[
y]]
superior, pero este último es preferible en Bash.
Tenga en cuenta lo que hacen los dos puntos arriba. De los documentos :
Dicho de otra manera, si se incluyen los dos puntos, el operador prueba la existencia de ambos parámetros y que su valor no es nulo; si se omiten los dos puntos, el operador solo prueba la existencia.
Al parecer, no hay necesidad de -n
o -z
.
En resumen, normalmente puedo usar [[ "${VAR:?}" ]]
. Según los ejemplos, esto imprime un error y sale si una variable es nula o no está establecida.
Puedes usar
if [[ ${WHATEVER:+$WHATEVER} ]]; then
pero
if [[ "${WHATEVER:+isset}" == "isset" ]]; then
podría ser más legible.
=
operador estándar (POSIX) , no ==
para ayudar en la portabilidad, y en [
lugar de hacerlo [[
si es posible.
set -o nounset
cuál es específica de bash. Si coloca un #!/bin/bash
en la parte superior de su secuencia de comandos, en realidad es mejor usar las mejoras de bash.
Si bien este no es exactamente el caso de uso solicitado anteriormente, descubrí que si desea usar nounset
(o -u
) el comportamiento predeterminado es el que desea: salir de cero con un mensaje descriptivo.
Me tomó bastante tiempo darme cuenta de esto y pensé que valía la pena publicarlo como solución.
Si todo lo que quieres es hacer eco de algo más al salir o hacer algo de limpieza, puedes usar una trampa.
El :-
operador es probablemente lo que desea de otra manera.