2352 votes

Comment vérifier si une variable est définie dans Bash ?

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 ?
}

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.

3284voto

Lionel Points 1655

(Habituellement) La bonne manière

if [ -z ${var+x} ]; then echo "var is unset"; else echo "var is set to '$var'"; fi

${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.

Digression de citations

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é.

(Souvent) De la mauvaise façon

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.

53 votes

@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" ] .

18 votes

Ç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).

0 votes

Cette solution fonctionne également si vous avez rendu bash strict en utilisant 'set u' pour provoquer une erreur sur les variables indéfinies.

1316voto

mbrannig Points 2491

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

114 votes

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é.

26 votes

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.

9 votes

Je suis d'accord, [] fonctionne mieux, notamment pour les scripts shell (non-bash).

768voto

Jens Points 17702

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           | ""              |
+--------------------+----------------------+-----------------+-----------------+

0 votes

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.

8 votes

@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 ...

0 votes

Comment le premier exemple peut-il faire écho à "foo" ? Comment "foo" intervient-il dans $1 ?

459voto

Russell Harmon Points 358

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 .

14 votes

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'

45 votes

L'argument '-v' de l'utilitaire 'test' a été ajouté dans bash 4.2.

23 votes

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.

216voto

ennuikiller Points 28005

Il existe de nombreuses façons d'y parvenir, dont les suivantes :

if [ -z "$1" ]

Cela réussit si $1 est nul ou non défini.

0 votes

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.

58 votes

Il existe une différence entre un paramètre non défini et un paramètre dont la valeur est nulle.

29 votes

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.com

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.

Powered by:

X