Comment savoir si une variable est définie dans Bash ?
Par exemple, comment vérifier si l'utilisateur a donné le premier paramètre à une fonction ?
function a {
# if $1 is set ?
}
Comment savoir si une variable est définie dans Bash ?
Par exemple, comment vérifier si l'utilisateur a donné le premier paramètre à une fonction ?
function a {
# if $1 is set ?
}
if [ -z ${var+x} ]; then echo "var is unset"; else echo "var is set to '$var'"; fi
où ${var+x}
est un expansion des paramètres qui ne vaut rien si var
n'est pas défini, et remplace la chaîne x
autrement.
Les guillemets peuvent être omis (nous pouvons donc dire ${var+x}
au lieu de "${var+x}"
) parce que cette syntaxe et cette utilisation garantissent qu'il ne se développera que vers quelque chose qui ne nécessite pas de guillemets (puisqu'il se développe soit en x
(qui ne contient pas de coupure de mots et n'a donc pas besoin de guillemets), ou à rien (ce qui donne comme résultat [ -z ]
qui, comme par hasard, donne la même valeur (vrai) que celle de [ -z "" ]
le fait aussi)).
Cependant, bien que les guillemets puissent être omis en toute sécurité, et que cela n'ait pas été immédiatement évident pour tous (ce n'était même pas évident pour le premier auteur de cette explication de citations qui est aussi un important codeur Bash), il serait parfois préférable d'écrire la solution entre guillemets comme suit [ -z "${var+x}" ]
au coût très faible d'une pénalité de vitesse O(1). Le premier auteur a également ajouté ce commentaire à côté du code utilisant cette solution en donnant l'URL de cette réponse, qui inclut maintenant aussi l'explication de la raison pour laquelle les guillemets peuvent être omis en toute sécurité.
if [ -z "$var" ]; then echo "var is blank"; else echo "var is set to '$var'"; fi
Cette méthode est souvent erronée car elle ne fait pas la distinction entre une variable qui n'est pas définie et une variable qui est définie par une chaîne vide. En d'autres termes, si var=''
alors la solution ci-dessus produira le message "var is blank".
La distinction entre unset et "set to the empty string" est essentielle dans les situations où l'utilisateur doit spécifier une extension, ou une liste supplémentaire de propriétés, et que le fait de ne pas les spécifier entraîne par défaut une valeur non vide, alors que le fait de spécifier la chaîne vide devrait faire que le script utilise une extension vide ou une liste de propriétés supplémentaires.
Cette distinction n'est toutefois pas indispensable dans tous les cas de figure. Dans ces cas [ -z "$var" ]
sera très bien.
@Garrett, votre modification a rendu cette réponse incorrecte, ${var+x}
est la substitution correcte à utiliser. Utilisation de [ -z ${var:+x} ]
ne produit pas de résultat différent de celui [ -z "$var" ]
.
Ça ne marche pas. J'obtiens "not set", que var ait une valeur ou non (effacé avec "unset var", "echo $var" ne produit aucun résultat).
Cette solution fonctionne également si vous avez rendu bash strict en utilisant 'set u' pour provoquer une erreur sur les variables indéfinies.
Pour vérifier si une variable de type chaîne est non nulle/non zéro, c'est-à-dire si elle est définie, utilisez
if [ -n "$1" ]
C'est le contraire de -z
. Je me retrouve à utiliser -n
plus que -z
.
Vous l'utiliseriez comme :
if [ -n "$1" ]; then
echo "You supplied the first parameter!"
else
echo "First parameter not supplied."
fi
Je préfère généralement [[ ]]
sur [ ]
comme [[ ]]
est plus puissant et cause moins de problèmes dans certaines situations (voir cette question pour une explication de la différence entre les deux). La question demande spécifiquement une bash et ne mentionne aucune exigence de portabilité.
La question est de savoir comment on peut voir si une variable est set . Alors vous ne pouvez pas supposer que la variable est set.
Voici comment tester si un paramètre est non activé o empty ("Null") o défini avec une valeur :
+--------------------+----------------------+-----------------+-----------------+
| Expression | parameter | parameter | parameter |
| in script: | Set and Not Null | Set But Null | Unset |
+--------------------+----------------------+-----------------+-----------------+
| ${parameter:-word} | substitute parameter | substitute word | substitute word |
| ${parameter-word} | substitute parameter | substitute null | substitute word |
| ${parameter:=word} | substitute parameter | assign word | assign word |
| ${parameter=word} | substitute parameter | substitute null | assign word |
| ${parameter:?word} | substitute parameter | error, exit | error, exit |
| ${parameter?word} | substitute parameter | substitute null | error, exit |
| ${parameter:+word} | substitute word | substitute null | substitute null |
| ${parameter+word} | substitute word | substitute word | substitute null |
+--------------------+----------------------+-----------------+-----------------+
Fuente: POSIX : Expansion des paramètres :
Dans tous les cas indiqués par "substitute", l'expression est remplacée par la valeur indiquée. Dans tous les cas indiqués par "assign", le paramètre se voit attribuer cette valeur, qui remplace également l'expression.
Pour montrer cela en action :
+--------------------+----------------------+-----------------+-----------------+
| Expression | FOO="world" | FOO="" | unset FOO |
| in script: | (Set and Not Null) | (Set But Null) | (Unset) |
+--------------------+----------------------+-----------------+-----------------+
| ${FOO:-hello} | world | hello | hello |
| ${FOO-hello} | world | "" | hello |
| ${FOO:=hello} | world | FOO=hello | FOO=hello |
| ${FOO=hello} | world | "" | FOO=hello |
| ${FOO:?hello} | world | error, exit | error, exit |
| ${FOO?hello} | world | "" | error, exit |
| ${FOO:+hello} | hello | "" | "" |
| ${FOO+hello} | hello | hello | "" |
+--------------------+----------------------+-----------------+-----------------+
Cela ne fonctionne pas si le paramètre est 1
, c'est-à-dire si vous voulez vérifier si le premier argument d'un script est défini ou non.
@HelloGoodbye Oui, cela fonctionne : set foo; echo ${1:-set but null or unset}
echos "foo" ; set --; echo ${1:-set but null or unset}
echoes set mais null ...
Comment le premier exemple peut-il faire écho à "foo" ? Comment "foo" intervient-il dans $1
?
Bien que la plupart des techniques énoncées ici soient correctes, bash 4.2 supporte un test réel pour la présence d'une variable ( coup d'homme ), plutôt que de tester la valeur de la variable.
[[ -v foo ]]; echo $?
# 1
foo=bar
[[ -v foo ]]; echo $?
# 0
foo=""
[[ -v foo ]]; echo $?
# 0
Notamment, cette approche ne provoquera pas d'erreur lorsqu'elle est utilisée pour vérifier la présence d'une variable non définie dans le fichier set -u
/ set -o nounset
contrairement à de nombreuses autres approches, comme l'utilisation du mode [ -z
.
Dans bash 4.1.2, que la variable soit définie ou non, [[ -v aaa ]]; echo $?
==> -bash: conditional binary operator expected
-bash: syntax error near 'aaa'
L'argument -v a été ajouté en complément de l'option shell -u (nounset). Lorsque l'option 'nounset' est activée (set -u), l'interpréteur de commandes renvoie une erreur et se termine, s'il n'est pas interactif. $# était bon pour vérifier les paramètres positionnels. Cependant, les variables nommées avaient besoin d'un autre moyen, autre que le clobbering, pour les identifier comme non définies. Il est regrettable que cette fonctionnalité soit arrivée si tard, car beaucoup sont tenus d'être compatibles avec les versions antérieures, auquel cas ils ne peuvent pas l'utiliser. La seule autre option est d'utiliser des astuces ou des "hacks" pour la contourner, comme indiqué ci-dessus, mais c'est très inélégant.
Je pense que cela doit être plus rapide que la méthode commune [ x "$var" = x ]. Je voulais juste le signaler. Il existe de nombreuses solutions mais pour les fous qui utilisent bash comme substitut de perl, c'est important.
Il existe une différence entre un paramètre non défini et un paramètre dont la valeur est nulle.
Je veux juste être pédant et souligner que c'est le en face de réponse à ce que la question pose. La question demande si la variable EST définie, et non si la variable n'est pas définie.
Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.
17 votes
if test $# -gt 0; then printf 'arg <%s>\n' "$@"; fi
.283 votes
Note aux chercheurs de solutions : Il existe de nombreuses réponses très bien notées à cette question qui répondent à la question "la variable est-elle non vide". Les solutions les plus correctes ("is variable set") sont mentionnées dans les réponses de Jens et Lionel ci-dessous.
12 votes
Aussi Russell Harmon et Seamus ont raison avec leur
-v
bien qu'il semble qu'il ne soit disponible que sur les nouvelles versions de l'application.bash
et non portable d'une coquille à l'autre.6 votes
Comme l'a souligné @NathanKidd, les solutions correctes sont données par Lionel et Jens. prosseek, vous devez changer votre réponse acceptée à l'un d'entre eux.
4 votes
... ou la réponse incorrecte pourrait être déclassée par les plus perspicaces d'entre nous, puisque @prosseek ne traite pas le problème.
0 votes
J'utilise souvent la substitution de paramètres avec
${1?"Usage: func_name first_arg"}
comme mentionné dans deux réponses ( stackoverflow.com/a/9087674/116891 et un autre) ci-dessous, car il arrêtera le script pour moi et imprimera un message utile.1 votes
@user, si le fait d'exiger Bash 4.2 est acceptable, cette réponse semble bonne, mais pour la plupart des gens, je doute que le fait de devoir ajouter des vérifications de la version de Bash soit la meilleure solution.
0 votes
Une discussion sur la manière de procéder avec des variables multiples est présentée à l'adresse suivante stackoverflow.com/q/27291287/873282
0 votes
Comme indiqué dans le commentaire stackoverflow.com/a/17538964/2169092 en utilisant if [ -v foo ] ; then ... vérifie directement si $foo est défini. Remarque : le $ manquant dans [ -v foo ] est correct.
0 votes
Poste connexe : Test pour une chaîne de longueur non nulle dans Bash : -n "$var" vs "$var". .
1 votes
Un autre conseil simple, mais utile, est le suivant
which {varname}
(dans le terminal/ligne de commande). Cela vous indiquera si une commande existe avec le même nom. Il est bon de le savoir dans certaines circonstances pour ne pas appeler accidentellement un programme.