J'ai quelques scripts shell Unix où je dois vérifier que certaines variables d'environnement sont définies avant de commencer à faire des choses, donc je fais ce genre de chose:
if [ -z "$STATE" ]; then
echo "Need to set STATE"
exit 1
fi
if [ -z "$DEST" ]; then
echo "Need to set DEST"
exit 1
fi
ce qui est beaucoup de frappe. Existe-t-il un idiome plus élégant pour vérifier qu'un ensemble de variables d'environnement est défini?
EDIT: Je devrais mentionner que ces variables n'ont pas de valeur par défaut significative - le script devrait sortir en erreur s'il n'y en a pas.
Réponses:
Expansion des paramètres
La réponse évidente est d'utiliser l'une des formes spéciales d'expansion des paramètres:
Ou mieux (voir la section «Position des guillemets doubles» ci-dessous):
La première variante (en utilisant simplement
?
) nécessite que STATE soit défini, mais STATE = "" (une chaîne vide) est OK - pas exactement ce que vous voulez, mais la notation alternative et plus ancienne.La deuxième variante (en utilisant
:?
) nécessite que DEST soit défini et non vide.Si vous ne fournissez aucun message, le shell fournit un message par défaut.
La
${var?}
construction est portable vers la version 7 UNIX et le Bourne Shell (1978 ou environ). La${var:?}
construction est un peu plus récente: je pense que c'était dans System III UNIX vers 1981, mais peut-être dans PWB UNIX avant cela. Il se trouve donc dans le Korn Shell, et dans les shells POSIX, notamment spécifiquement Bash.Il est généralement documenté dans la page de manuel du shell dans une section appelée Expansion des paramètres . Par exemple, le
bash
manuel dit:Le Colon Command
Je devrais probablement ajouter que la commande colon a simplement ses arguments évalués puis réussit. C'est la notation originale du commentaire du shell (avant '
#
' jusqu'à la fin de la ligne). Pendant longtemps, les scripts shell Bourne ont eu deux points comme premier caractère. Le C Shell lirait un script et utiliserait le premier caractère pour déterminer s'il s'agissait du C Shell (un '#
' hachage) ou du Bourne shell (un ':
' deux-points). Ensuite, le noyau est intervenu et a ajouté un support pour les commentaires '#!/path/to/program
' et le shell Bourne '#
', et la convention du côlon a été abandonnée. Mais si vous tombez sur un script qui commence par deux points, vous saurez maintenant pourquoi.Position des guillemets doubles
Blong a demandé dans un commentaire :
L'essentiel de la discussion est:
La réponse courte est "faites comme
shellcheck
suggéré":Pour illustrer pourquoi, étudiez ce qui suit. Notez que la
:
commande ne fait pas écho à ses arguments (mais le shell évalue les arguments). Nous voulons voir les arguments, donc le code ci-dessous utiliseprintf "%s\n"
à la place de:
.Notez comment la valeur de
$x
est développée en premier*
, puis une liste de noms de fichiers lorsque l'expression globale n'est pas entre guillemets. C'est ce quishellcheck
recommande devrait être corrigé. Je n'ai pas vérifié qu'il ne s'oppose pas au formulaire où l'expression est placée entre guillemets, mais c'est une supposition raisonnable que ce serait OK.la source
if [ "$variable" = "abc" ]; then : OK; else : variable is not set correctly; fi
.Essaye ça:
la source
[ -z "$STATE" ] && { echo "Need to set STATE"; exit 1; }
voir ce billet de blogVotre question dépend du shell que vous utilisez.
La coquille de Bourne laisse très peu de ce que vous recherchez.
MAIS...
Cela fonctionne, à peu près partout.
Essayez simplement de rester loin de csh. Il était bon pour les cloches et les sifflets qu'il a ajoutés, comparé à la coque Bourne, mais il grince vraiment maintenant. Si vous ne me croyez pas, essayez simplement de séparer STDERR dans csh! (-:
Il y a deux possibilités ici. L'exemple ci-dessus, à savoir en utilisant:
pour la première fois, vous devez vous référer à $ MyVariable. Cela prend l'env. var MyVariable et, s'il n'est actuellement pas défini, affecte la valeur de SomeDefault à la variable pour une utilisation ultérieure.
Vous avez également la possibilité de:
qui substitue simplement SomeDefault à la variable dans laquelle vous utilisez cette construction. Il n'affecte pas la valeur SomeDefault à la variable, et la valeur de MyVariable sera toujours nulle après que cette instruction soit rencontrée.
la source
Assurément, l'approche la plus simple consiste à ajouter le
-u
commutateur au shebang (la ligne en haut de votre script), en supposant que vous utilisezbash
:#!/bin/sh -u
Cela entraînera la fermeture du script si des variables non liées se cachent à l'intérieur.
la source
Si
MyVariable
est défini et non nul, il réinitialisera la valeur de la variable (= rien ne se passe).Sinon,
MyVariable
est réglé surSomeDefault
.Ce qui précède tentera de s'exécuter
${MyVariable}
, donc si vous voulez juste définir la variable, faites:la source
À mon avis, la vérification la plus simple et la plus compatible pour #! / Bin / sh est:
Encore une fois, c'est pour / bin / sh et est également compatible avec les anciens systèmes Solaris.
la source
/bin/sh
qui prend en charge la${var:?}
notation, etc.unset MYVAR
etMYVAR=
.foo
n'est pas défini,"$foo"
se développe toujours dans la chaîne vide.bash
4.2 a introduit l'-v
opérateur qui teste si un nom est défini sur n'importe quelle valeur, même la chaîne vide.la source
J'ai toujours utilisé:
Pas beaucoup plus concis, je le crains.
Sous CSH, vous avez $? STATE.
la source
STATE
est vide ou non défini, pas seulement non défini.Pour de futures personnes comme moi, je voulais faire un pas en avant et paramétrer le nom var, donc je peux parcourir une liste de noms de variables de taille variable:
la source
Nous pouvons écrire une belle assertion pour vérifier un tas de variables à la fois:
Exemple d'appel:
Production:
Plus d'assertions de ce type ici: https://github.com/codeforester/base/blob/master/lib/assertions.sh
la source
Cela peut aussi être un moyen:
http://unstableme.blogspot.com/2007/02/checks-whether-envvar-is-set-or-not.html
la source
Aucune des solutions ci-dessus n'a fonctionné pour mes besoins, en partie parce que je vérifie l'environnement pour une liste ouverte de variables qui doivent être définies avant de démarrer un long processus. Je me suis retrouvé avec ceci:
la source
Plutôt que d'utiliser des scripts shell externes, j'ai tendance à charger des fonctions dans mon shell de connexion. J'utilise quelque chose comme ça comme fonction d'aide pour vérifier les variables d'environnement plutôt que n'importe quelle variable définie:
la source
is_this_an_env_variable P
retournera le succès parce qu'ilPATH
existe.La
$?
syntaxe est assez soignée:la source
$?
l'état de sortie de la commande précédente;$?BLAH
est la chaîne constituée de l'état de sortie de la commande précédente concaténée avec 'BLAH'. Cela ne teste pas du$BLAH
tout la variable . (Il y a une rumeur selon laquelle cela pourrait faire plus ou moins ce qui est requiscsh
, mais les coquillages sont mieux laissés sur le bord de la mer.)