Le code suivant se termine avec une erreur de variable indépendante. Comment résoudre ce problème, tout en utilisant l' set -o
option nounset?
#!/bin/bash
set -o nounset
if [ ! -z ${WHATEVER} ];
then echo "yo"
fi
echo "whatever"
Réponses:
#!/bin/bash
set -o nounset
VALUE=${WHATEVER:-}
if [ ! -z ${VALUE} ];
then echo "yo"
fi
echo "whatever"
Dans ce cas, VALUE
finit par être une chaîne vide s'il WHATEVER
n'est pas défini. Nous utilisons l' {parameter:-word}
extension, que vous pouvez consulter man bash
sous "Extension des paramètres".
:-
vérifie si la variable n'est pas définie ou vide. Si vous voulez vérifier que si elle est hors service, utilisez -
: VALUE=${WHATEVER-}
. Aussi, un moyen plus lisible de vérifier si une variable est vide:if [ "${WHATEVER+defined}" = defined ]; then echo defined; else echo undefined; fi
$WHATEVER
contient uniquement des espaces - Voir ma réponse.
! -z
" au lieu de simplement " -n
"?
Vous devez citer les variables si vous souhaitez obtenir le résultat attendu:
check() {
if [ -n "${WHATEVER-}" ]
then
echo 'not empty'
elif [ "${WHATEVER+defined}" = defined ]
then
echo 'empty but defined'
else
echo 'unset'
fi
}
Tester:
$ unset WHATEVER
$ check
unset
$ WHATEVER=
$ check
empty but defined
$ WHATEVER=' '
$ check
not empty
"info bash"
, "${WHATEVER-}"
devrait avoir un ":"
(deux points) avant le "-"
(tiret) comme: "${WHATEVER:-}"
et "${WHATEVER+defined}"
devrait avoir deux points avant la "+"
(plus) comme: "${WHATEVER:+defined}"
. Pour moi, cela fonctionne dans les deux sens, avec ou sans le colon. Sur certaines versions de 'nix, cela ne fonctionnera probablement pas sans inclure les deux points, donc il devrait probablement être ajouté.
-
, +
, :+
et :-
sont tous pris en charge. Le premier détecte si la variable est définie , et le second détecte si elle est définie ou vide . From man bash
: "L'omission des deux-points entraîne un test uniquement pour un paramètre qui n'est pas défini."
Que diriez-vous d'un oneliner?
[ -z "${VAR:-}" ] && echo "VAR is not set or is empty" || echo "VAR is set to $VAR"
-z
vérifie à la fois la variable vide ou non définie
-z
vérifie uniquement si le paramètre suivant est vide. -z
C'est juste un argument de la [
commande. L'expansion variable se produit avant de [ -z
pouvoir faire quoi que ce soit.
Hypothèses:
$ 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 vous souhaitez qu'un script non interactif imprime une erreur et quitte si une variable est nulle ou non définie:
$ [[ "${HOME:?}" ]]
$ [[ "${IAMUNBOUND:?}" ]]
bash: IAMUNBOUND: parameter null or not set
$ IAMNULL=""
$ [[ "${IAMNULL:?}" ]]
bash: IAMNULL: parameter null or not set
Si vous ne souhaitez pas que le script se ferme:
$ [[ "${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.
Vous pouvez même utiliser [
et ]
au lieu de [[
et ]]
au - dessus, mais ce dernier est préférable dans Bash.
Notez ce que fait les deux points ci-dessus. À partir de la documentation :
En d'autres termes, si le signe deux-points est inclus, l'opérateur teste à la fois l'existence du paramètre et que sa valeur n'est pas nulle; si le signe deux-points est omis, l'opérateur ne teste que l'existence.
Il n'y a apparemment pas besoin de -n
ou -z
.
En résumé, je peux généralement utiliser simplement [[ "${VAR:?}" ]]
. Selon les exemples, cela imprime une erreur et se termine si une variable est nulle ou non définie.
Vous pouvez utiliser
if [[ ${WHATEVER:+$WHATEVER} ]]; then
mais
if [[ "${WHATEVER:+isset}" == "isset" ]]; then
pourrait être plus lisible.
=
opérateur standard (POSIX) , pas ==
pour aider à la portabilité, et [
au lieu de [[
si possible.
set -o nounset
ce qui est spécifique à bash. Si vous mettez un #!/bin/bash
en haut de votre script, il est en fait préférable d'utiliser les améliorations de bash.
Bien que ce ne soit pas exactement le cas d'utilisation demandé ci-dessus, j'ai constaté que si vous souhaitez utiliser nounset
(ou -u
) le comportement par défaut est celui que vous souhaitez: quitter une valeur différente de zéro avec un message descriptif.
Il m'a fallu suffisamment de temps pour m'en rendre compte que j'ai pensé que cela valait la peine d'être publié comme solution.
Si tout ce que vous voulez est de faire écho à quelque chose d'autre en quittant, ou de faire un nettoyage, vous pouvez utiliser un piège.
L' :-
opérateur est probablement ce que vous voulez autrement.