définir l'utilisation -u ne fonctionne pas comme prévu

12

J'apprends à utiliser efficacement différentes setoptions dans mon script et je suis tombé sur ce set -uqui semble être parfait pour quitter mon script si une variable n'est pas définie correctement (par exemple, supprimer des utilisateurs). Selon l' homme page set -uet set -efait ce qui suit ...

-e  Exit immediately if a command exits with a non-zero status.
-u  Treat unset variables as an error when substituting.

J'ai créé un script de test pour tester cette fonctionnalité, mais il ne semble pas fonctionner comme prévu. Peut-être que quelqu'un pourrait mieux m'expliquer mon problème et où je fais une mauvaise interprétation? Le script de test est ci-dessous. Je vous remercie.

set -e
set -u
testing="This works"
echo $?
echo ${testing}
testing2=
echo $?
echo ${testing2}
testing3="This should not appear"
echo $?
echo ${testing3}

Je m'attends à ce que le script affiche 0 et "Cela fonctionne" , puis échoue car il ${testing2}n'est pas défini.

Au lieu de cela, je suis affiché 0 et "Cela fonctionne" , suivi de 0 puis de 0 Cela ne devrait pas apparaître

Quelqu'un peut-il fournir des connaissances? Je vous remercie.

Azifor
la source
1
Alors, suivi ... existe-t-il un moyen de rendre illégal la définition d'une variable dans la chaîne nulle / de déclencher une erreur? Je suppose que non.
Luke Davis

Réponses:

10

De "l'homme Bash":

Un paramètre est défini si une valeur lui a été affectée. La chaîne nulle est une valeur valide. Une fois qu'une variable est définie, elle ne peut être désactivée qu'en utilisant la commande intégrée unset.

Lorsque vous le faites, testing2=vous définissez la variable sur la chaîne nulle.

Remplacez-le par unset testing2et réessayez.


Le set -en'aide pas dans ce cas car une affectation n'a jamais de code de sortie de 1. Essayez ceci pour voir que la dernière commande exécutée (l'affectation) a un code de sortie de 0, ou lisez cette question :

$ false; a=""; echo $?
0

Et je crois aussi que l'utilisation de set -e est plus un problème qu'une solution.

Ce qui peut obtenir une erreur avec l'utilisation de variables non définies est set -u:

#!/bin/bash
set -u
testing="This works"
echo ${testing}
unset testing2
echo ${testing2}
testing3="This should not appear"
echo ${testing3}

Sortira:

$  ./script.sh
This works
./script.sh: line 9: testing2: unbound variable
Communauté
la source
3

testing2=définit la testing2variable sur une chaîne vide; la variable est en fait définie .

Cependant, si vous deviez exécuter echo $testing99dans un shell Bash interactif (sans paramètre errexit, c'est-à-dire set -e), vous obtiendriez une erreur:

bash: testing99: unbound variable

De côté

En testant les scripts tout à l'heure, j'ai découvert qu'un shell interactif ne se ferme pas toujours lorsque l'on tente de développer une variable qui n'a pas été définie alors qu'un shell non interactif (exécutant un script shell) se ferme toujours . Selon la page de manuel POSIX pour set:

-u Le shell doit écrire un message d'erreur standard lorsqu'il essaie de développer une variable qui n'est pas définie et de quitter immédiatement. Un shell interactif ne doit pas quitter.

Un shell Bash interactif ne se fermera que s'il errexita également été défini. D'un autre côté, un shell de tableau de bord interactif ne sortira pas - même s'il set -ea déjà été exécuté.

Anthony Geoghegan
la source
Si le tiret ne se termine pas avec set -e; set -u; unset aa; echo $ aa, alors le tiret est faux.
schily
@schily Lorsque j'ai remarqué cela pour la première fois, je me suis dit que les auteurs du tableau de bord le savaient mieux que moi et qu'il y avait peut-être une certaine ambiguïté dans les spécifications POSIX, mais après avoir revérifié pubs.opengroup.org/onlinepubs/9699919799/utilities/… , je d'accord qui ressemble à un bug, d'accord.
Anthony Geoghegan
Il existe une règle simple: lorsque Korn Shell et Bourne Shell sont d'accord et qu'une autre implémentation de shell présente une déviation, l'autre shell se comporte de manière incorrecte.
schily