if test $# -gt 0; then printf 'arg <%s>\n' "$@"; fi.
Jens
211
Note aux chercheurs de solutions: Il existe de nombreuses réponses très bien notées à cette question qui répondent à la question «est variable non vide». Les solutions de correction les plus nombreuses ("est un ensemble variable") sont mentionnées dans les réponses de Jens et Lionel ci-dessous.
Nathan Kidd
8
Russell Harmon et Seamus sont également corrects avec leur -vtest, bien que cela ne soit apparemment disponible que sur les nouvelles versions de bashet non portable sur les coques.
Graeme
5
Comme l'a souligné @NathanKidd, les solutions correctes sont données par Lionel et Jens. prosseek, vous devez remplacer votre réponse acceptée par l'une de ces réponses .
Garrett
3
... ou la réponse incorrecte pourrait être rejetée par les plus exigeants d'entre nous, car @prosseek ne résout pas le problème.
dan3
Réponses:
2305
(Habituellement) La bonne façon
if[-z ${var+x}];then echo "var is unset";else echo "var is set to '$var'";fi
où ${var+x}est une extension de paramètre qui n'évalue rien si elle varn'est pas définie et remplace la chaîne xautrement.
Citations Digression
Les guillemets peuvent être omis (nous pouvons donc dire à la ${var+x}place de "${var+x}") car cette syntaxe et cette utilisation garantissent que cela ne s'étendra qu'à quelque chose qui ne nécessite pas de guillemets (car il se développe soit x(qui ne contient pas de sauts de mots donc il n'a pas besoin de guillemets)), ou rien (ce qui se traduit par [ -z ], qui s'évalue commodément à la même valeur (vrai) qui le [ -z "" ]fait aussi)).
Cependant, bien que les citations puissent être omises en toute sécurité, et ce n'était pas immédiatement évident pour tous (ce n'était même pas apparent pour le premier auteur de cette explication de citations qui est également un codeur Bash majeur), il serait parfois préférable d'écrire la solution avec des guillemets comme [ -z "${var+x}" ], au tout petit coût possible d'une pénalité de vitesse O (1). Le premier auteur a également ajouté cela en tant que commentaire à côté du code en utilisant cette solution donnant l'URL de cette réponse, qui comprend désormais également l'explication des raisons pour lesquelles les guillemets peuvent être omis en toute sécurité.
(Souvent) dans le mauvais sens
if[-z "$var"];then echo "var is blank";else echo "var is set to '$var'";fi
C'est souvent faux car cela ne fait pas de distinction entre une variable non définie et une variable définie sur la chaîne vide. Autrement dit, si var='', alors la solution ci-dessus affichera "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 ne pas les spécifier par défaut est une valeur non vide, alors que la spécification de la chaîne vide doit faire en sorte que le script utilise une extension vide ou une liste de propriétés supplémentaires.
La distinction peut ne pas être cependant essentielle dans tous les scénarios. Dans ces cas, tout [ -z "$var" ]ira bien.
@ Garrett, votre modification a rendu cette réponse incorrecte, ${var+x}c'est la substitution correcte à utiliser. L'utilisation [ -z ${var:+x} ]ne produit aucun résultat différent de [ -z "$var" ].
Graeme
11
Ça ne marche pas. Je reçois "non défini", que var soit défini sur une valeur ou non (effacé avec "unset var", "echo $ var" ne produit aucune sortie).
Brent212
10
Pour la syntaxe $ {paramètre + mot} de la solution, la section du manuel officiel est gnu.org/software/bash/manual/… ; cependant, un bug dans cela, il ne mentionne pas très clairement cette syntaxe mais dit juste quote (Omettre les deux-points [":"] entraîne un test uniquement pour un paramètre qui n'est pas défini. .. $ {paramètre: + mot} [signifie] Si le paramètre est nul ou non défini, rien n'est substitué, sinon l'expansion du mot est substituée.); la référence citée pubs.opengroup.org/onlinepubs/9699919799/utilities/… (bon à savoir) contient des documents beaucoup plus clairs ici.
Destiny Architect
7
Il semble que des guillemets soient requis lorsque vous utilisez plusieurs expressions, par exemple [ -z "" -a -z ${var+x} ]obtient bash: [: argument expecteddans bash 4.3-ubuntu (mais pas par exemple zsh). Je n'aime vraiment pas la réponse en utilisant une syntaxe qui fonctionne dans certains cas.
FauxFaux
41
Utiliser un simple [ -z $var ]n'est pas plus «faux» que d'omettre des guillemets. Quoi qu'il en soit, vous faites des hypothèses sur votre contribution. Si vous traitez bien une chaîne vide comme non définie, [ -z $var ]c'est tout ce dont vous avez besoin.
nshew
910
Pour vérifier la variable de chaîne non nulle / non nulle, c'est-à-dire si elle est définie, utilisez
if[-n "$1"]
C'est l'opposé de -z. Je me retrouve en utilisant -nplus 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 [[ ]]plus [ ], car il [[ ]]est plus puissant et provoque 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 solution bash et ne mentionne aucune exigence de portabilité.
Flow du
18
La question est de savoir comment on peut voir si une variable est définie . Ensuite, vous ne pouvez pas supposer que la variable est définie.
HelloGoodbye
7
Je suis d'accord, []fonctionne mieux en particulier pour les scripts shell (non-bash).
Hengjie
73
Échoue set -u.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
63
Notez que -nc'est le test par défaut, donc plus simplement [ "$1" ]ou [[ $1 ]]travaillez aussi. Notez également que la [[ ]]citation n'est pas nécessaire .
TNE
479
Voici comment tester si un paramètre est non défini , ou vide ("Null") ou défini avec une valeur :
+--------------------+----------------------+-----------------+-----------------+|Expression| parameter | parameter | parameter ||in script:|Set and NotNull|SetButNull|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 |+--------------------+----------------------+-----------------+-----------------+
Dans tous les cas indiqués par "substitut", l'expression est remplacée par la valeur indiquée. Dans tous les cas affichés avec "assign", le paramètre reçoit cette valeur, qui remplace également l'expression.
Pour le montrer en action:
+--------------------+----------------------+-----------------+-----------------+|Expression| FOO="world"| FOO=""| unset FOO ||in script:|(Set and NotNull)|(SetButNull)|(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 |""|+--------------------+----------------------+-----------------+-----------------+
@HelloGoodbye Oui, cela fonctionne: set foo; echo ${1:-set but null or unset}echos "foo"; set --; echo ${1:-set but null or unset}échos définis mais nuls ...
Jens
4
@HelloGoodbye Les paramètres de position peuvent être réglés avec, euh, set:-)
Jens
95
Cette réponse est très déroutante. Des exemples pratiques sur la façon d'utiliser ce tableau?
Ben Davis
12
@BenDavis Les détails sont expliqués dans le lien vers la norme POSIX, qui fait référence au chapitre duquel le tableau est extrait. Une construction que j'utilise dans presque tous les scripts que j'écris consiste : ${FOOBAR:=/etc/foobar.conf}à définir une valeur par défaut pour une variable si elle est non définie ou nulle.
Jens
1
parameterest un nom de variable. wordest une chaîne à remplacer en fonction de la syntaxe dans la table que vous utilisez, et si la variable $parameterest définie, définie mais nulle ou non définie. Pas pour compliquer les choses, mais wordpeut aussi inclure des variables! Cela peut être très utile pour passer des arguments optionnels séparés par un caractère. Par exemple: ${parameter:+,${parameter}}génère une virgule séparée ,$parametersi elle est définie mais pas nulle. Dans ce cas, wordest,${parameter}
TrinitronX
260
Bien que la plupart des techniques indiquées ici soient correctes, bash 4.2 prend en charge un test réel de la présence d'une variable ( man bash ), plutôt que de tester la valeur de la variable.
Notamment, cette approche ne provoquera pas d'erreur lorsqu'elle est utilisée pour rechercher une variable non définie dans le mode set -u/ set -o nounset, contrairement à de nombreuses autres approches, telles que l'utilisation [ -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'
Dan
32
L'argument '-v' du module intégré 'test' a été ajouté dans bash 4.2.
Ti Strga
19
l'argument -v a été ajouté en complément de l'option shell -u (jeu de noms). Avec 'nounset' activé (set -u), le shell retournera une erreur et se terminera, s'il n'est pas interactif. $ # était bon pour vérifier les paramètres de position. Cependant, les variables nommées devaient être identifiées comme non définies d'une autre manière que le clobbering. Il est regrettable que cette fonctionnalité soit arrivée si tard car beaucoup sont susceptibles d'être compatibles avec les versions antérieures, auquel cas ils ne peuvent pas l'utiliser. La seule autre option consiste à utiliser des astuces ou des «hacks» pour contourner le problème, comme indiqué ci-dessus, mais c'est le plus inélégant.
osirisgothra
2
Notez que cela ne fonctionne pas pour les variables déclarées mais non définies. par exempledeclare -a foo
miken32
17
C'est pourquoi je continue à lire après la réponse acceptée / la plus votée.
Joe
176
Il existe de nombreuses façons de procéder, les éléments suivants étant l'un d'eux:
Il existe une différence entre un paramètre non défini et un paramètre avec une valeur nulle.
chepner
21
Je veux juste être pédant et souligner que c'est la réponse opposée à ce que la question pose. La question demande si la variable EST définie, pas si la variable n'est pas définie.
Philluminati
47
[[ ]]n'est rien d'autre qu'un piège de portabilité. if [ -n "$1" ]devrait être utilisé ici.
Jens
73
Cette réponse est incorrecte. La question demande un moyen de savoir si une variable est définie, pas si elle est définie sur une valeur non vide. Étant donné foo="", $fooa une valeur, mais -zsignalera simplement qu'il est vide. Et -z $fooexplosera si vous en avez set -o nounset.
Keith Thompson
4
Cela dépend de la définition de "variable est définie". Si vous souhaitez vérifier si la variable est définie sur une chaîne non nulle , la réponse mbranning est correcte. Mais si vous voulez vérifier si la variable est déclarée mais pas initialisée (ie foo=), alors la réponse de Russel est correcte.
Flow du
77
Je trouve toujours la table POSIX lente dans l' autre réponse , alors voici mon point de vue:
Notez que chaque groupe (avec et sans deux-points précédents) a les mêmes cas définis et non définis , donc la seule chose qui diffère est la façon dont les cas vides sont traités.
Avec les deux-points précédents, les cas vides et non définis sont identiques, donc j'utiliserais ceux là où c'est possible (c'est-à-dire :=, pas seulement =parce que le cas vide est incohérent).
Rubriques:
set moyen VARIABLEn'est pas vide ( VARIABLE="something")
vide signifie VARIABLEvide / null ( VARIABLE="")
unset signifie qu'il VARIABLEn'existe pas ( unset VARIABLE)
Valeurs:
$VARIABLE signifie que le résultat est la valeur d'origine de la variable.
"default" signifie que le résultat était la chaîne de remplacement fournie.
"" signifie que le résultat est nul (une chaîne vide).
exit 127 signifie que le script cesse de s'exécuter avec le code de sortie 127.
$(VARIABLE="default")signifie que le résultat est la valeur d'origine de la variable et que la chaîne de remplacement fournie est affectée à la variable pour une utilisation future.
Vous avez corrigé uniquement celles qui sont de véritables erreurs de codage (instances d'indirection indésirable lorsque vous travaillez avec des variables). J'ai fait une modification pour corriger quelques cas supplémentaires où le dollar fait une différence dans l'interprétation de la description. BTW, toutes les variables de shell (à l'exception des tableaux) sont des variables de chaîne; il peut simplement arriver qu'ils contiennent une chaîne qui peut être interprétée comme un nombre. Parler de chaînes ne fait qu'embrouiller le message. Les citations n'ont rien à voir avec les chaînes, elles sont juste une alternative à l'évasion. VARIABLE=""pourrait s'écrire VARIABLE=. Pourtant, le premier est plus lisible.
Palec
Merci pour le tableau, il est très utile, mais j'essaie de quitter le script s'il n'est pas défini ou vide. Mais le code de sortie que je reçois est 1 et non 127.
Astronaute
64
Pour voir si une variable n'est pas vide, j'utilise
if[[ $var ]];then...# `$var' expands to a nonempty string
L'inverse teste si une variable est non définie ou vide:
if[[! $var ]];then...# `$var' expands to the empty string (set or not)
Pour voir si une variable est définie (vide ou non vide), j'utilise
if[[ ${var+x}]];then...# `var' exists (empty or nonempty)if[[ ${1+x}]];then...# Parameter 1 exists (empty or nonempty)
Les tests opposés si une variable n'est pas définie:
if[[! ${var+x}]];then...# `var' is not set at allif[[! ${1+x}]];then...# We were called with no arguments
Moi aussi, j'utilise ça depuis un moment; juste d'une manière réduite:[ $isMac ] && param="--enable-shared"
@Bhaskar Je pense que c'est parce que cette réponse a déjà fourni essentiellement la même réponse (utiliser ${variable+x}pour obtenir xiff $variableest défini) presque six mois plus tôt. Il contient également beaucoup plus de détails expliquant pourquoi il a raison.
Mark Haferkamp
mais ${variable+x}est moins lisible (et évident)
knocte
35
Sur une version moderne de Bash (4.2 ou plus tard je pense; je ne sais pas avec certitude), j'essaierais ceci:
if[!-v SOMEVARIABLE ]#note the lack of a $ sigilthen
echo "Variable is unset"elif[-z "$SOMEVARIABLE"]then
echo "Variable is set to an empty string"else
echo "Variable is set to some string"fi
Notez également que ce [ -v "$VARNAME" ]n'est pas incorrect, mais effectue simplement un test différent. Supposons VARNAME=foo; il vérifie ensuite si une variable nommée fooest définie.
chepner
5
Remarque pour ceux qui souhaitent la portabilité, -vn'est pas conforme à POSIX
kzh
Si l'on obtient [: -v: unexpected operator, il faut s'assurer d'utiliser à la bashplace de sh.
koppor
25
if["$1"!=""];then
echo \$1 is setelse
echo \$1 is not setfi
Bien que pour les arguments, il est normalement préférable de tester $ #, qui est le nombre d'arguments, à mon avis.
if[ $# -gt 0 ]; then
echo \$1 is setelse
echo \$1 is not setfi
Le premier test est en arrière; Je pense que vous voulez [ "$1" != "" ](ou [ -n "$1" ]) ...
Gordon Davisson
10
Cela échouera si $1est défini sur la chaîne vide.
HelloGoodbye
2
La deuxième partie de la réponse (paramètres de comptage) est une solution de contournement utile pour la première partie de la réponse qui ne fonctionne pas lorsqu'elle $1est définie sur une chaîne vide.
Mark Berry
Cela échouera s'il set -o nounsetest activé.
Flimm
21
Remarque
Je donne une réponse fortement axée sur Bash à cause de la bashbalise.
Réponse courte
Tant que vous ne traitez que des variables nommées dans Bash, cette fonction devrait toujours vous dire si la variable a été définie, même s'il s'agit d'un tableau vide.
variable-is-set(){
declare -p "$1"&>/dev/null
}
Pourquoi cela fonctionne
Dans Bash (au moins aussi tôt que 3.0), si varest une variable déclarée / définie, declare -p vargénère alors une declarecommande qui définirait la variable varquel que soit son type et sa valeur actuels, et renvoie le code d'état 0(succès). Si varn'est pas déclaré, declare -p vargénère un message d'erreur stderret renvoie le code d'état 1. En utilisant &>/dev/null, redirige à la fois normal stdoutet stderrsortie vers /dev/null, pour ne jamais être vu, et sans changer le code d'état. Ainsi, la fonction ne renvoie que le code d'état.
Pourquoi d'autres méthodes échouent (parfois) dans Bash
[ -n "$var" ]: Ceci vérifie uniquement si ${var[0]}non vide. (Dans Bash, $varc'est la même chose que ${var[0]}.)
[ -n "${var+x}" ]: Ceci vérifie uniquement si ${var[0]}est défini.
[ "${#var[@]}" != 0 ]: Ceci vérifie uniquement si au moins un index de $varest défini.
Lorsque cette méthode échoue dans Bash
Cela ne fonctionne que pour les variables nommées (y compris $_), et non pas certaines variables spéciales ( $!, $@, $#, $$, $*, $?, $-, $0, $1, $2, ... et tout ce que je peut avoir oublié). Comme aucun de ces tableaux n'est un tableau, le style POSIX [ -n "${var+x}" ]fonctionne pour toutes ces variables spéciales. Mais méfiez-vous de l'encapsuler dans une fonction car de nombreuses variables spéciales changent de valeurs / d'existence lorsque des fonctions sont appelées.
Note de compatibilité du shell
Si votre script contient des tableaux et que vous essayez de le rendre compatible avec autant de shells que possible, envisagez d'utiliser typeset -pplutôt que declare -p. J'ai lu que ksh ne supporte que le premier, mais je n'ai pas pu tester cela. Je sais que Bash 3.0+ et Zsh 5.5.1 prennent chacun en charge les deux typeset -pet declare -p, ne différant que dans lequel l'un est une alternative à l'autre. Mais je n'ai pas testé de différences au-delà de ces deux mots clés, et je n'ai pas testé d'autres shells.
Si vous avez besoin que votre script soit compatible avec POSIX sh, vous ne pouvez pas utiliser de tableaux. Sans tableaux, [ -n "{$var+x}" ]fonctionne.
Code de comparaison pour différentes méthodes dans Bash
Cette fonction supprime la variable var, evals le code transmis, exécute des tests pour déterminer si elle varest définie par le evalcode d et affiche enfin les codes d'état résultants pour les différents tests.
Je saute test -v var, [ -v var ]et [[ -v var ]]parce qu'ils donnent des résultats identiques à la norme POSIX [ -n "${var+x}" ], tout en nécessitant Bash 4.2+. Je saute également typeset -pparce que c'est la même chose que declare -pdans les shells que j'ai testés (Bash 3.0 à 5.0 et Zsh 5.5.1).
is-var-set-after(){# Set var by passed expression.
unset var
eval"$1"# Run the tests, in increasing order of accuracy.[-n "$var"]# (index 0 of) var is nonempty
nonempty=$?[-n "${var+x}"]# (index 0 of) var is set, maybe empty
plus=$?["${#var[@]}"!=0]# var has at least one index set, maybe empty
count=$?
declare -p var &>/dev/null # var has been declared (any type)
declared=$?# Show test results.
printf '%30s: %2s %2s %2s %2s\n'"$1" $nonempty $plus $count $declared
}
Code de cas de test
Notez que les résultats des tests peuvent être inattendus car Bash traite les indices de tableau non numériques comme "0" si la variable n'a pas été déclarée comme un tableau associatif. De plus, les tableaux associatifs ne sont valables que dans Bash 4.0+.
# Header.
printf '%30s: %2s %2s %2s %2s\n'"test"'-n''+x''#@''-p'# First 5 tests: Equivalent to setting 'var=foo' because index 0 of an# indexed array is also the nonindexed value, and non-numerical# indices in an array not declared as associative are the same as# index 0.
is-var-set-after "var=foo"# 0 0 0 0
is-var-set-after "var=(foo)"# 0 0 0 0
is-var-set-after "var=([0]=foo)"# 0 0 0 0
is-var-set-after "var=([x]=foo)"# 0 0 0 0
is-var-set-after "var=([y]=bar [x]=foo)"# 0 0 0 0# '[ -n "$var" ]' fails when var is empty.
is-var-set-after "var=''"# 1 0 0 0
is-var-set-after "var=([0]='')"# 1 0 0 0# Indices other than 0 are not detected by '[ -n "$var" ]' or by# '[ -n "${var+x}" ]'.
is-var-set-after "var=([1]='')"# 1 1 0 0
is-var-set-after "var=([1]=foo)"# 1 1 0 0
is-var-set-after "declare -A var; var=([x]=foo)"# 1 1 0 0# Empty arrays are only detected by 'declare -p'.
is-var-set-after "var=()"# 1 1 1 0
is-var-set-after "declare -a var"# 1 1 1 0
is-var-set-after "declare -A var"# 1 1 1 0# If 'var' is unset, then it even fails the 'declare -p var' test.
is-var-set-after "unset var"# 1 1 1 1
Sortie test
Les mnémoniques de test dans la rangée correspond à l'en- tête de [ -n "$var" ], [ -n "${var+x}" ], [ "${#var[@]}" != 0 ], et declare -p var, respectivement.
declare -p var &>/dev/null est (100%?) fiable pour tester les variables nommées dans Bash depuis au moins 3.0.
[ -n "${var+x}" ] est fiable dans les situations conformes POSIX, mais ne peut pas gérer les tableaux.
Il existe d'autres tests pour vérifier si une variable n'est pas vide et pour vérifier les variables déclarées dans d'autres shells. Mais ces tests ne conviennent ni aux scripts Bash ni POSIX.
Parmi les réponses que j'ai essayées, celle-ci ( declare -p var &>/dev/null) est la SEULE qui fonctionne. MERCI!
user1387866
2
@ mark-haferkamp J'ai essayé de modifier votre réponse pour ajouter le "/" précédent critique à votre code de fonction afin qu'il se lise, ... &> /dev/nullmais SO ne m'a pas permis de modifier un seul caractère 🙄 (doit être> 6 caractères - j'ai même essayé d'ajouter un espace blanc mais cela n'a pas fonctionné). En outre, il peut être utile de modifier la fonction pour basculer vers $1un exemple de variable nommée (par exemple OUTPUT_DIR) car, comme vous l'avez souligné, les variables spéciales comme $1ne fonctionnent pas ici. Quoi qu'il en soit, il s'agit d'une modification critique sinon le code cherche à créer un fichier appelé nulldans un répertoire relatif appelé dev. BTW - excellente réponse!
joehanna
De plus, l'utilisation du nom de la variable sans le préfixe $ fonctionne également: declare -p PATH &> /dev/nullrenvoie 0 où as declare -p ASDFASDGFASKDF &> /dev/nullrenvoie 1. (sur bash 5.0.11 (1) -release)
joehanna
1
Bon travail! 1 mot d'avertissement: declare vardéclare var une variable mais ne pas défini en termes de set -o nounset: Test avecdeclare foo bar=; set -o nounset; echo $bar; echo $foo
Xebeche
@joehanna Merci d'avoir rattrapé ce manquant /! J'ai corrigé cela, mais je pense que la logique est assez confuse pour justifier une fonction, surtout à la lumière du commentaire de @ xebeche. @xebeche C'est gênant pour ma réponse.… Il semble que je vais devoir essayer quelque chose comme declare -p "$1" | grep =ou test -v "$1".
Mark Haferkamp
19
Pour ceux qui cherchent à vérifier s'il n'est pas défini ou vide lorsqu'ils sont dans un script avec set -u:
if[-z "${var-}"];then
echo "Must provide var environment variable. Exiting...."
exit 1fi
La [ -z "$var" ]vérification régulière échouera avec var; unbound variableif set -umais se [ -z "${var-}" ]développera en chaîne vide si elle varn'est pas définie sans échec.
Il vous manque un deux-points. Ça devrait l'être ${var:-}, non ${var-}. Mais dans Bash, je peux confirmer que cela fonctionne même sans le colon.
Palec
3
${var:-}et ${var-}signifient des choses différentes. ${var:-}se développera en chaîne vide si varnon définie ou nulle et ${var-}se développera en chaîne vide uniquement si non définie.
RubenLaguna
Je viens d'apprendre quelque chose de nouveau, merci! L'omission des deux points entraîne un test uniquement pour un paramètre non défini. Autrement dit, si le signe deux-points est inclus, l'opérateur teste l'existence du paramètre et sa valeur n'est pas nulle; si le deux-points est omis, l'opérateur teste uniquement l'existence. Cela ne fait aucune différence ici, mais bon à savoir.
Palec
17
Vous souhaitez quitter s'il n'est pas défini
Cela a fonctionné pour moi. Je voulais que mon script se termine avec un message d'erreur si aucun paramètre n'était défini.
#!/usr/bin/env bashset-o errexit
# Get the value and empty validation check all in one
VER="${1:?You must pass a version of the format 0.0.0 as the only argument}"
Cela renvoie une erreur lors de son exécution
peek@peek:~$ ./setver.sh
./setver.sh: line 13:1:You must pass a version of the format 0.0.0 as the only argument
Vérifier uniquement, pas de sortie - Vide et Non défini sont INVALIDES
Essayez cette option si vous voulez simplement vérifier si la valeur set = VALID ou unset / empty = INVALID.
Pour vérifier si une variable est définie avec une valeur non vide, utilisez [ -n "$x" ], comme d'autres l'ont déjà indiqué.
La plupart du temps, c'est une bonne idée de traiter une variable qui a une valeur vide de la même manière qu'une variable qui n'est pas définie. Mais vous pouvez distinguer les deux si vous avez besoin de: [ -n "${x+set}" ](se "${x+set}"développe en setsi xest défini et à la chaîne vide si elle xn'est pas définie).
Pour vérifier si un paramètre a été passé, test $#, qui est le nombre de paramètres passés à la fonction (ou au script, quand il n'est pas dans une fonction) (voir la réponse de Paul ).
Lisez la section "Extension des paramètres" de la bashpage de manuel. L'extension de paramètre ne fournit pas de test général pour une variable en cours de définition, mais il y a plusieurs choses que vous pouvez faire pour un paramètre s'il n'est pas défini.
Par exemple:
function a {
first_arg=${1-foo}# rest of the function}
sera first_argégal à $1s'il est attribué, sinon il utilise la valeur "foo". Si vous adevez absolument prendre un seul paramètre, et qu'aucune bonne valeur par défaut n'existe, vous pouvez quitter avec un message d'erreur quand aucun paramètre n'est donné:
function a {: ${1?a must take a single argument}# rest of the function}
(Notez l'utilisation de :as comme une commande null, qui ne fait qu'expanser les valeurs de ses arguments. Nous ne voulons rien faire avec $1dans cet exemple, quittez simplement s'il n'est pas défini)
L'utilisation [[ -z "$var" ]]est le moyen le plus simple de savoir si une variable a été définie ou non, mais cette option -zne fait pas de distinction entre une variable non définie et une variable définie sur une chaîne vide:
Les réponses ci-dessus ne fonctionnent pas lorsque l'option Bash set -uest activée. De plus, ils ne sont pas dynamiques, par exemple, comment tester une variable dont le nom "factice" est défini? Essaye ça:
is_var_defined(){if[ $# -ne 1 ]then
echo "Expected exactly one argument: variable name as string, e.g., 'my_var'"
exit 1fi# Tricky. Since Bash option 'set -u' may be enabled, we cannot directly test if a variable# is defined with this construct: [ ! -z "$var" ]. Instead, we must use default value# substitution with this construct: [ ! -z "${var:-}" ]. Normally, a default value follows the# operator ':-', but here we leave it blank for empty (null) string. Finally, we need to# substitute the text from $1 as 'var'. This is not allowed directly in Bash with this# construct: [ ! -z "${$1:-}" ]. We need to use indirection with eval operator.# Example: $1="var"# Expansion for eval operator: "[ ! -z \${$1:-} ]" -> "[ ! -z \${var:-} ]"# Code execute: [ ! -z ${var:-} ]eval"[ ! -z \${$1:-} ]"return $?# Pedantic.}
$ var=10
$ if! ${var+false};then echo "is set";else echo "NOT set";fi
is set
$ unset -v var
$ if! ${var+false};then echo "is set";else echo "NOT set";fi
NOT set
Donc, fondamentalement, si une variable est définie, elle devient "une négation du résultat false" (ce qui sera true= "est défini").
Et, s'il n'est pas défini, il deviendra "une négation du résultat true" (comme le résultat vide l'évalue true) (ainsi finira comme étant false= "NON défini").
if[[ ${1:+isset}]]then echo "It was set and not null.">&2else echo "It was not set or it was null.">&2fiif[[ ${1+isset}]]then echo "It was set but might be null.">&2else echo "It was was not set.">&2fi
Bienvenue dans StackOverflow. Bien que votre réponse soit appréciée, il est préférable de donner plus que du code. Pourriez-vous ajouter un raisonnement à votre réponse ou une petite explication? Voir cette page pour d'autres idées sur l'élargissement de votre réponse.
Celeo
0
C'est ce que j'utilise tous les jours:
## Check if a variable is set# param1 name of the variable#function is_set(){[[-n "${1}"]]&& test -n "$(eval "echo "\${${1}+x}"")"}
Cela fonctionne bien sous Linux et Solaris jusqu'à bash 3.0.
Depuis Bash 2.0+, l'expansion indirecte est disponible. Vous pouvez remplacer le long et complexe (avec un eval également inclus) test -n "$(eval "echo "\${${1}+x}"")"pour l'équivalent:[[ ${!1+x} ]]
0
J'aime les fonctions auxiliaires pour cacher les détails grossiers de bash. Dans ce cas, cela ajoute encore plus de grossièreté (cachée):
# The first ! negates the result (can't use -n to achieve this)# the second ! expands the content of varname (can't do ${$varname})functionIsDeclared_Tricky{local varname="$1"![-z ${!varname+x}]}
Parce que j'avais d'abord eu des bugs dans cette implémentation (inspirée des réponses de Jens et Lionel), j'ai trouvé une solution différente:
# Ask for the properties of the variable - fails if not declaredfunctionIsDeclared(){
declare -p $1 &>/dev/null
}
Je trouve que c'est plus simple, plus timide et plus facile à comprendre / à retenir. Le cas de test montre qu'il est équivalent:
function main(){
declare -i xyz
local foo
local bar=local baz=''IsDeclared_Tricky xyz; echo "IsDeclared_Tricky xyz: $?"IsDeclared_Tricky foo; echo "IsDeclared_Tricky foo: $?"IsDeclared_Tricky bar; echo "IsDeclared_Tricky bar: $?"IsDeclared_Tricky baz; echo "IsDeclared_Tricky baz: $?"IsDeclared xyz; echo "IsDeclared xyz: $?"IsDeclared foo; echo "IsDeclared foo: $?"IsDeclared bar; echo "IsDeclared bar: $?"IsDeclared baz; echo "IsDeclared baz: $?"}
main
Le cas de test montre également que local varne déclare PAS var (sauf s'il est suivi de '='). Pendant un certain temps, j'ai pensé que je déclarais les variables de cette façon, juste pour découvrir maintenant que j'ai simplement exprimé mon intention ... C'est un no-op, je suppose.
J'utilise principalement ce test pour donner (et retourner) des paramètres aux fonctions de manière quelque peu "élégante" et sûre (ressemblant presque à une interface ...):
#auxiliary functionsfunction die(){
echo "Error: $1"; exit 1}function assertVariableDeclared(){IsDeclared"$1"|| die "variable not declared: $1"}function expectVariables(){while(( $# > 0 )); do
assertVariableDeclared $1; shift
done}# actual examplefunction exampleFunction(){
expectVariables inputStr outputStr
outputStr="$inputStr world!"}function bonus(){local inputStr='Hello'local outputStr=# remove this to trigger error
exampleFunction
echo $outputStr
}
bonus
Si appelé avec toutes les variables requises déclarées:
ne fonctionnera pas lorsque vous aurez set -uen effet ce qui affichera l' unboud variableerreur
Michael Heuberger
0
Sommaire
Utilisez test -n "${var-}"pour vérifier si la variable n'est pas vide (et doit donc être définie / définie également)
Utilisez test ! -z "${var+}"pour vérifier si la variable est définie / définie (même si elle est vide)
Notez que le premier cas d'utilisation est beaucoup plus courant dans les scripts shell et c'est ce que vous voudrez généralement utiliser.
Remarques
Cette solution devrait fonctionner dans tous les shells POSIX (sh, bash, zsh, ksh, dash)
Certaines des autres réponses à cette question sont correctes mais peuvent prêter à confusion pour les personnes n'ayant pas d'expérience dans les scripts shell, donc je voulais fournir une réponse TLDR qui sera le moins déroutant pour ces personnes.
Explication
Pour comprendre le fonctionnement de cette solution, vous devez comprendre la commande POSIXtest et l'expansion des paramètres du shell POSIX ( spéc ), nous allons donc couvrir les bases absolues nécessaires pour comprendre la réponse.
La commande test évalue une expression et renvoie vrai ou faux (via son état de sortie). L'opérateur -nrenvoie true si l'opérande est une chaîne non vide. Ainsi, par exemple, test -n "a"renvoie true, tandis que test -n ""renvoie false. Maintenant, pour vérifier si une variable n'est pas vide (ce qui signifie qu'elle doit être définie), vous pouvez utiliser test -n "$var". Cependant, certains scripts shell ont une option set ( set -u) qui fait que toute référence à des variables non définies émet une erreur, donc si la variable varn'est pas définie, l'expression $aprovoquera une erreur. Pour gérer ce cas correctement, vous devez utiliser l'expansion de variable, qui indiquera au shell de remplacer la variable par une chaîne alternative si elle n'est pas définie, en évitant l'erreur susmentionnée.
L'extension de la variable ${var-}signifie: si la variable varn'est pas définie (également appelée "unset"), remplacez-la par une chaîne vide. Donc test -n "${var-}", retournera true si $varn'est pas vide, ce qui est presque toujours ce que vous voulez vérifier dans les scripts shell. La vérification inverse, si elle $varn'est pas définie ou n'est pas vide, le serait test -z "${var-}".
Passons maintenant au deuxième cas d'utilisation: vérifier si la variable varest définie, qu'elle soit vide ou non. Il s'agit d'un cas d'utilisation moins courant et légèrement plus complexe, et je vous conseille de lire la grande réponse de Lionels pour mieux la comprendre.
Je pense que tu veux dire set -o nounset, non set -o noun set. Cela ne fonctionne que pour les variables qui ont été exportéditées. Il modifie également vos paramètres d'une manière difficile à annuler.
if test $# -gt 0; then printf 'arg <%s>\n' "$@"; fi
.-v
test, bien que cela ne soit apparemment disponible que sur les nouvelles versions debash
et non portable sur les coques.Réponses:
(Habituellement) La bonne façon
où
${var+x}
est une extension de paramètre qui n'évalue rien si ellevar
n'est pas définie et remplace la chaînex
autrement.Citations Digression
Les guillemets peuvent être omis (nous pouvons donc dire à la
${var+x}
place de"${var+x}"
) car cette syntaxe et cette utilisation garantissent que cela ne s'étendra qu'à quelque chose qui ne nécessite pas de guillemets (car il se développe soitx
(qui ne contient pas de sauts de mots donc il n'a pas besoin de guillemets)), ou rien (ce qui se traduit par[ -z ]
, qui s'évalue commodément à la même valeur (vrai) qui le[ -z "" ]
fait aussi)).Cependant, bien que les citations puissent être omises en toute sécurité, et ce n'était pas immédiatement évident pour tous (ce n'était même pas apparent pour le premier auteur de cette explication de citations qui est également un codeur Bash majeur), il serait parfois préférable d'écrire la solution avec des guillemets comme
[ -z "${var+x}" ]
, au tout petit coût possible d'une pénalité de vitesse O (1). Le premier auteur a également ajouté cela en tant que commentaire à côté du code en utilisant cette solution donnant l'URL de cette réponse, qui comprend désormais également l'explication des raisons pour lesquelles les guillemets peuvent être omis en toute sécurité.(Souvent) dans le mauvais sens
C'est souvent faux car cela ne fait pas de distinction entre une variable non définie et une variable définie sur la chaîne vide. Autrement dit, si
var=''
, alors la solution ci-dessus affichera "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 ne pas les spécifier par défaut est une valeur non vide, alors que la spécification de la chaîne vide doit faire en sorte que le script utilise une extension vide ou une liste de propriétés supplémentaires.
La distinction peut ne pas être cependant essentielle dans tous les scénarios. Dans ces cas, tout
[ -z "$var" ]
ira bien.la source
${var+x}
c'est la substitution correcte à utiliser. L'utilisation[ -z ${var:+x} ]
ne produit aucun résultat différent de[ -z "$var" ]
.[ -z "" -a -z ${var+x} ]
obtientbash: [: argument expected
dans bash 4.3-ubuntu (mais pas par exemple zsh). Je n'aime vraiment pas la réponse en utilisant une syntaxe qui fonctionne dans certains cas.[ -z $var ]
n'est pas plus «faux» que d'omettre des guillemets. Quoi qu'il en soit, vous faites des hypothèses sur votre contribution. Si vous traitez bien une chaîne vide comme non définie,[ -z $var ]
c'est tout ce dont vous avez besoin.Pour vérifier la variable de chaîne non nulle / non nulle, c'est-à-dire si elle est définie, utilisez
C'est l'opposé de
-z
. Je me retrouve en utilisant-n
plus que-z
.Vous l'utiliseriez comme:
la source
[[ ]]
plus[ ]
, car il[[ ]]
est plus puissant et provoque 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 solution bash et ne mentionne aucune exigence de portabilité.[]
fonctionne mieux en particulier pour les scripts shell (non-bash).set -u
.-n
c'est le test par défaut, donc plus simplement[ "$1" ]
ou[[ $1 ]]
travaillez aussi. Notez également que la[[ ]]
citation n'est pas nécessaire .Voici comment tester si un paramètre est non défini , ou vide ("Null") ou défini avec une valeur :
Source: POSIX: Extension des paramètres :
Pour le montrer en action:
la source
set foo; echo ${1:-set but null or unset}
echos "foo";set --; echo ${1:-set but null or unset}
échos définis mais nuls ...set
:-): ${FOOBAR:=/etc/foobar.conf}
à définir une valeur par défaut pour une variable si elle est non définie ou nulle.parameter
est un nom de variable.word
est une chaîne à remplacer en fonction de la syntaxe dans la table que vous utilisez, et si la variable$parameter
est définie, définie mais nulle ou non définie. Pas pour compliquer les choses, maisword
peut aussi inclure des variables! Cela peut être très utile pour passer des arguments optionnels séparés par un caractère. Par exemple:${parameter:+,${parameter}}
génère une virgule séparée,$parameter
si elle est définie mais pas nulle. Dans ce cas,word
est,${parameter}
Bien que la plupart des techniques indiquées ici soient correctes, bash 4.2 prend en charge un test réel de la présence d'une variable ( man bash ), plutôt que de tester la valeur de la variable.
Notamment, cette approche ne provoquera pas d'erreur lorsqu'elle est utilisée pour rechercher une variable non définie dans le mode
set -u
/set -o nounset
, contrairement à de nombreuses autres approches, telles que l'utilisation[ -z
.la source
[[ -v aaa ]]; echo $?
==>-bash: conditional binary operator expected
-bash: syntax error near 'aaa'
declare -a foo
Il existe de nombreuses façons de procéder, les éléments suivants étant l'un d'eux:
Cela réussit si $ 1 est nul ou non défini
la source
[[ ]]
n'est rien d'autre qu'un piège de portabilité.if [ -n "$1" ]
devrait être utilisé ici.foo=""
,$foo
a une valeur, mais-z
signalera simplement qu'il est vide. Et-z $foo
explosera si vous en avezset -o nounset
.foo=
), alors la réponse de Russel est correcte.Je trouve toujours la table POSIX lente dans l' autre réponse , alors voici mon point de vue:
Notez que chaque groupe (avec et sans deux-points précédents) a les mêmes cas définis et non définis , donc la seule chose qui diffère est la façon dont les cas vides sont traités.
Avec les deux-points précédents, les cas vides et non définis sont identiques, donc j'utiliserais ceux là où c'est possible (c'est-à-dire
:=
, pas seulement=
parce que le cas vide est incohérent).Rubriques:
VARIABLE
n'est pas vide (VARIABLE="something"
)VARIABLE
vide / null (VARIABLE=""
)VARIABLE
n'existe pas (unset VARIABLE
)Valeurs:
$VARIABLE
signifie que le résultat est la valeur d'origine de la variable."default"
signifie que le résultat était la chaîne de remplacement fournie.""
signifie que le résultat est nul (une chaîne vide).exit 127
signifie que le script cesse de s'exécuter avec le code de sortie 127.$(VARIABLE="default")
signifie que le résultat est la valeur d'origine de la variable et que la chaîne de remplacement fournie est affectée à la variable pour une utilisation future.la source
VARIABLE=""
pourrait s'écrireVARIABLE=
. Pourtant, le premier est plus lisible.Pour voir si une variable n'est pas vide, j'utilise
L'inverse teste si une variable est non définie ou vide:
Pour voir si une variable est définie (vide ou non vide), j'utilise
Les tests opposés si une variable n'est pas définie:
la source
[ $isMac ] && param="--enable-shared"
${variable+x}
pour obtenirx
iff$variable
est défini) presque six mois plus tôt. Il contient également beaucoup plus de détails expliquant pourquoi il a raison.${variable+x}
est moins lisible (et évident)Sur une version moderne de Bash (4.2 ou plus tard je pense; je ne sais pas avec certitude), j'essaierais ceci:
la source
[ -v "$VARNAME" ]
n'est pas incorrect, mais effectue simplement un test différent. SupposonsVARNAME=foo
; il vérifie ensuite si une variable nomméefoo
est définie.-v
n'est pas conforme à POSIX[: -v: unexpected operator
, il faut s'assurer d'utiliser à labash
place desh
.Bien que pour les arguments, il est normalement préférable de tester $ #, qui est le nombre d'arguments, à mon avis.
la source
[ "$1" != "" ]
(ou[ -n "$1" ]
) ...$1
est défini sur la chaîne vide.$1
est définie sur une chaîne vide.set -o nounset
est activé.Remarque
Je donne une réponse fortement axée sur Bash à cause de la
bash
balise.Réponse courte
Tant que vous ne traitez que des variables nommées dans Bash, cette fonction devrait toujours vous dire si la variable a été définie, même s'il s'agit d'un tableau vide.
Pourquoi cela fonctionne
Dans Bash (au moins aussi tôt que 3.0), si
var
est une variable déclarée / définie,declare -p var
génère alors unedeclare
commande qui définirait la variablevar
quel que soit son type et sa valeur actuels, et renvoie le code d'état0
(succès). Sivar
n'est pas déclaré,declare -p var
génère un message d'erreurstderr
et renvoie le code d'état1
. En utilisant&>/dev/null
, redirige à la fois normalstdout
etstderr
sortie vers/dev/null
, pour ne jamais être vu, et sans changer le code d'état. Ainsi, la fonction ne renvoie que le code d'état.Pourquoi d'autres méthodes échouent (parfois) dans Bash
Lorsque cette méthode échoue dans Bash
Cela ne fonctionne que pour les variables nommées (y compris
$_
), et non pas certaines variables spéciales ($!
,$@
,$#
,$$
,$*
,$?
,$-
,$0
,$1
,$2
, ... et tout ce que je peut avoir oublié). Comme aucun de ces tableaux n'est un tableau, le style POSIX[ -n "${var+x}" ]
fonctionne pour toutes ces variables spéciales. Mais méfiez-vous de l'encapsuler dans une fonction car de nombreuses variables spéciales changent de valeurs / d'existence lorsque des fonctions sont appelées.Note de compatibilité du shell
Si votre script contient des tableaux et que vous essayez de le rendre compatible avec autant de shells que possible, envisagez d'utiliser
typeset -p
plutôt quedeclare -p
. J'ai lu que ksh ne supporte que le premier, mais je n'ai pas pu tester cela. Je sais que Bash 3.0+ et Zsh 5.5.1 prennent chacun en charge les deuxtypeset -p
etdeclare -p
, ne différant que dans lequel l'un est une alternative à l'autre. Mais je n'ai pas testé de différences au-delà de ces deux mots clés, et je n'ai pas testé d'autres shells.Si vous avez besoin que votre script soit compatible avec POSIX sh, vous ne pouvez pas utiliser de tableaux. Sans tableaux,
[ -n "{$var+x}" ]
fonctionne.Code de comparaison pour différentes méthodes dans Bash
Cette fonction supprime la variable
var
,eval
s le code transmis, exécute des tests pour déterminer si ellevar
est définie par leeval
code d et affiche enfin les codes d'état résultants pour les différents tests.Je saute
test -v var
,[ -v var ]
et[[ -v var ]]
parce qu'ils donnent des résultats identiques à la norme POSIX[ -n "${var+x}" ]
, tout en nécessitant Bash 4.2+. Je saute égalementtypeset -p
parce que c'est la même chose quedeclare -p
dans les shells que j'ai testés (Bash 3.0 à 5.0 et Zsh 5.5.1).Code de cas de test
Notez que les résultats des tests peuvent être inattendus car Bash traite les indices de tableau non numériques comme "0" si la variable n'a pas été déclarée comme un tableau associatif. De plus, les tableaux associatifs ne sont valables que dans Bash 4.0+.
Sortie test
Les mnémoniques de test dans la rangée correspond à l'en- tête de
[ -n "$var" ]
,[ -n "${var+x}" ]
,[ "${#var[@]}" != 0 ]
, etdeclare -p var
, respectivement.Sommaire
la source
declare -p var &>/dev/null
) est la SEULE qui fonctionne. MERCI!... &> /dev/null
mais SO ne m'a pas permis de modifier un seul caractère 🙄 (doit être> 6 caractères - j'ai même essayé d'ajouter un espace blanc mais cela n'a pas fonctionné). En outre, il peut être utile de modifier la fonction pour basculer vers$1
un exemple de variable nommée (par exempleOUTPUT_DIR
) car, comme vous l'avez souligné, les variables spéciales comme$1
ne fonctionnent pas ici. Quoi qu'il en soit, il s'agit d'une modification critique sinon le code cherche à créer un fichier appelénull
dans un répertoire relatif appelédev
. BTW - excellente réponse!declare -p PATH &> /dev/null
renvoie 0 où asdeclare -p ASDFASDGFASKDF &> /dev/null
renvoie 1. (sur bash 5.0.11 (1) -release)declare var
déclare var une variable mais ne pas défini en termes deset -o nounset
: Test avecdeclare foo bar=; set -o nounset; echo $bar; echo $foo
/
! J'ai corrigé cela, mais je pense que la logique est assez confuse pour justifier une fonction, surtout à la lumière du commentaire de @ xebeche. @xebeche C'est gênant pour ma réponse.… Il semble que je vais devoir essayer quelque chose commedeclare -p "$1" | grep =
outest -v "$1"
.Pour ceux qui cherchent à vérifier s'il n'est pas défini ou vide lorsqu'ils sont dans un script avec
set -u
:La
[ -z "$var" ]
vérification régulière échouera avecvar; unbound variable
ifset -u
mais se[ -z "${var-}" ]
développera en chaîne vide si ellevar
n'est pas définie sans échec.la source
${var:-}
, non${var-}
. Mais dans Bash, je peux confirmer que cela fonctionne même sans le colon.${var:-}
et${var-}
signifient des choses différentes.${var:-}
se développera en chaîne vide sivar
non définie ou nulle et${var-}
se développera en chaîne vide uniquement si non définie.Vous souhaitez quitter s'il n'est pas défini
Cela a fonctionné pour moi. Je voulais que mon script se termine avec un message d'erreur si aucun paramètre n'était défini.
Cela renvoie une erreur lors de son exécution
Vérifier uniquement, pas de sortie - Vide et Non défini sont INVALIDES
Essayez cette option si vous voulez simplement vérifier si la valeur set = VALID ou unset / empty = INVALID.
Ou, même de courts tests ;-)
Vérifier uniquement, pas de sortie - Seul le vide est invalide
Et c'est la réponse à la question. Utilisez ceci si vous voulez simplement vérifier si la valeur set / empty = VALID ou unset = INVALID.
REMARQUE, le "1" dans "..- 1}" est insignifiant, il peut être n'importe quoi (comme x)
Tests courts
Je dédie cette réponse à @ mklement0 (commentaires) qui m'a mis au défi de répondre à la question avec précision.
Référence http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_02
la source
Pour vérifier si une variable est définie avec une valeur non vide, utilisez
[ -n "$x" ]
, comme d'autres l'ont déjà indiqué.La plupart du temps, c'est une bonne idée de traiter une variable qui a une valeur vide de la même manière qu'une variable qui n'est pas définie. Mais vous pouvez distinguer les deux si vous avez besoin de:
[ -n "${x+set}" ]
(se"${x+set}"
développe enset
six
est défini et à la chaîne vide si ellex
n'est pas définie).Pour vérifier si un paramètre a été passé, test
$#
, qui est le nombre de paramètres passés à la fonction (ou au script, quand il n'est pas dans une fonction) (voir la réponse de Paul ).la source
Lisez la section "Extension des paramètres" de la
bash
page de manuel. L'extension de paramètre ne fournit pas de test général pour une variable en cours de définition, mais il y a plusieurs choses que vous pouvez faire pour un paramètre s'il n'est pas défini.Par exemple:
sera
first_arg
égal à$1
s'il est attribué, sinon il utilise la valeur "foo". Si vousa
devez absolument prendre un seul paramètre, et qu'aucune bonne valeur par défaut n'existe, vous pouvez quitter avec un message d'erreur quand aucun paramètre n'est donné:(Notez l'utilisation de
:
as comme une commande null, qui ne fait qu'expanser les valeurs de ses arguments. Nous ne voulons rien faire avec$1
dans cet exemple, quittez simplement s'il n'est pas défini)la source
: ${var?message}
.En bash, vous pouvez utiliser
-v
à l'intérieur du[[ ]]
module intégré:la source
L'utilisation
[[ -z "$var" ]]
est le moyen le plus simple de savoir si une variable a été définie ou non, mais cette option-z
ne fait pas de distinction entre une variable non définie et une variable définie sur une chaîne vide:Il est préférable de le vérifier en fonction du type de variable: variable env, paramètre ou variable régulière.
Pour une variable env:
Pour un paramètre (par exemple, pour vérifier l'existence d'un paramètre
$5
):Pour une variable régulière (en utilisant une fonction auxiliaire, pour le faire de manière élégante):
Remarques:
la source
Les réponses ci-dessus ne fonctionnent pas lorsque l'option Bash
set -u
est activée. De plus, ils ne sont pas dynamiques, par exemple, comment tester une variable dont le nom "factice" est défini? Essaye ça:Connexes: dans Bash, comment puis-je tester si une variable est définie en mode "-u"
la source
eval "[ ! -z \${$1:-} ]"
à l' évaluation indirecte:[ ! -z ${!1:-} ];
.Tu peux faire:
la source
-n
et ne pas le nier-z
.$1
, c'est-à-dire[ ! -z "$1" ]
. Ou vous pouvez écrire[[ ! -z $1 ]]
en bash / ksh / zsh.$1
est défini sur la chaîne vide.Ma façon préférée est la suivante:
Donc, fondamentalement, si une variable est définie, elle devient "une négation du résultat
false
" (ce qui seratrue
= "est défini").Et, s'il n'est pas défini, il deviendra "une négation du résultat
true
" (comme le résultat vide l'évaluetrue
) (ainsi finira comme étantfalse
= "NON défini").la source
Ou
Ou
Ou
la source
Dans un shell, vous pouvez utiliser l'
-z
opérateur qui est True si la longueur de la chaîne est nulle.Une simple ligne pour définir la valeur par défaut
MY_VAR
si elle n'est pas définie, sinon vous pouvez éventuellement afficher le message:la source
la source
$1
,$2
Et jusqu'à$N
est toujours activé. Désolé, c'est échoué.J'ai trouvé un (bien) meilleur code pour le faire si vous voulez vérifier quoi que ce soit
$@
.Pourquoi tout ça? Tout
$@
existe dans Bash, mais par défaut, il est vide,test -z
ettest -n
ne peut donc pas vous aider.Mise à jour: Vous pouvez également compter le nombre de caractères dans un paramètre.
la source
la source
C'est ce que j'utilise tous les jours:
Cela fonctionne bien sous Linux et Solaris jusqu'à bash 3.0.
la source
test -n "$(eval "echo "\${${1}+x}"")"
pour l'équivalent:[[ ${!1+x} ]]
J'aime les fonctions auxiliaires pour cacher les détails grossiers de bash. Dans ce cas, cela ajoute encore plus de grossièreté (cachée):
Parce que j'avais d'abord eu des bugs dans cette implémentation (inspirée des réponses de Jens et Lionel), j'ai trouvé une solution différente:
Je trouve que c'est plus simple, plus timide et plus facile à comprendre / à retenir. Le cas de test montre qu'il est équivalent:
Le cas de test montre également que
local var
ne déclare PAS var (sauf s'il est suivi de '='). Pendant un certain temps, j'ai pensé que je déclarais les variables de cette façon, juste pour découvrir maintenant que j'ai simplement exprimé mon intention ... C'est un no-op, je suppose.BONUS: utiliser
J'utilise principalement ce test pour donner (et retourner) des paramètres aux fonctions de manière quelque peu "élégante" et sûre (ressemblant presque à une interface ...):
Si appelé avec toutes les variables requises déclarées:
autre:
la source
Après avoir parcouru toutes les réponses, cela fonctionne également:
si vous ne mettez pas à la
SOME_VAR
place de ce que j'ai$SOME_VAR
, il le mettra à une valeur vide;$
est nécessaire pour que cela fonctionne.la source
set -u
en effet ce qui affichera l'unboud variable
erreurSommaire
test -n "${var-}"
pour vérifier si la variable n'est pas vide (et doit donc être définie / définie également)test ! -z "${var+}"
pour vérifier si la variable est définie / définie (même si elle est vide)Notez que le premier cas d'utilisation est beaucoup plus courant dans les scripts shell et c'est ce que vous voudrez généralement utiliser.
Remarques
Explication
Pour comprendre le fonctionnement de cette solution, vous devez comprendre la commande POSIX
test
et l'expansion des paramètres du shell POSIX ( spéc ), nous allons donc couvrir les bases absolues nécessaires pour comprendre la réponse.La commande test évalue une expression et renvoie vrai ou faux (via son état de sortie). L'opérateur
-n
renvoie true si l'opérande est une chaîne non vide. Ainsi, par exemple,test -n "a"
renvoie true, tandis quetest -n ""
renvoie false. Maintenant, pour vérifier si une variable n'est pas vide (ce qui signifie qu'elle doit être définie), vous pouvez utilisertest -n "$var"
. Cependant, certains scripts shell ont une option set (set -u
) qui fait que toute référence à des variables non définies émet une erreur, donc si la variablevar
n'est pas définie, l'expression$a
provoquera une erreur. Pour gérer ce cas correctement, vous devez utiliser l'expansion de variable, qui indiquera au shell de remplacer la variable par une chaîne alternative si elle n'est pas définie, en évitant l'erreur susmentionnée.L'extension de la variable
${var-}
signifie: si la variablevar
n'est pas définie (également appelée "unset"), remplacez-la par une chaîne vide. Donctest -n "${var-}"
, retournera true si$var
n'est pas vide, ce qui est presque toujours ce que vous voulez vérifier dans les scripts shell. La vérification inverse, si elle$var
n'est pas définie ou n'est pas vide, le seraittest -z "${var-}"
.Passons maintenant au deuxième cas d'utilisation: vérifier si la variable
var
est définie, qu'elle soit vide ou non. Il s'agit d'un cas d'utilisation moins courant et légèrement plus complexe, et je vous conseille de lire la grande réponse de Lionels pour mieux la comprendre.la source
Pour vérifier si une var est définie ou non
la source
$var
est défini sur la chaîne vide.Si vous souhaitez tester qu'une variable est liée ou non, cela fonctionne bien, même après avoir activé l'option nounset:
la source
set -o nounset
, nonset -o noun set
. Cela ne fonctionne que pour les variables qui ont étéexport
éditées. Il modifie également vos paramètres d'une manière difficile à annuler.