J'ai besoin de vérifier l'existence d'une variable dans une instruction if
. Quelque chose à l'effet de:
if [ -v $somevar ]
then
echo "Variable somevar exists!"
else
echo "Variable somevar does not exist!"
Et la question la plus proche était this , ce qui ne répond pas vraiment à ma question.
Dans bash moderne (version 4.2 et supérieure):
[[ -v name_of_var ]]
De help test
:
-v VAR, True si la variable Shell VAR est définie
Cela dépend de ce que vous entendez par existe.
Une variable déclarée mais non affectée existe-t-elle?
Est-ce qu'une variable de tableau (ou de hachage) à laquelle une liste vide a été affectée existe?
Est-ce qu'une variable nameref pointant vers une variable qui n'est actuellement pas affectée existe?
Considérez-vous $-
, $#
, $1
variables? (POSIX ne le fait pas).
Dans les obus de type Bourne, la voie canonique est:
if [ -n "${var+set}" ]; then
echo '$var was set'
fi
Cela fonctionne pour les variables scalaires et autres paramètres pour dire si une variable a été affectée à une valeur (vide ou non, automatiquement, de l'environnement, des affectations, read
, for
ou autre).
Pour les shells qui ont une commande typeset
ou declare
, cela ne rapporterait pas comme set les variables qui ont été déclarées mais pas - affecté sauf dans zsh
.
Pour les shells qui prennent en charge les tableaux, à l'exception de yash
et zsh
qui ne seraient pas signalés comme set variables de tableau, sauf si l'élément d'indice 0 a été défini.
Pour bash
(mais pas ksh93
ni zsh
), pour les variables de type tableau associatif, qui ne les rapporterait pas comme set à moins que leur élément de clé "0" n'ait été défini .
Pour ksh93
et bash
, pour les variables de type nameref, qui ne renvoie vrai que si la variable référencée par le nameref est elle-même considérée set.
Pour ksh
, zsh
et bash
, une meilleure approche pourrait être:
if ((${#var[@]})); then
echo '$var (or the variable it references for namerefs) or any of its elements for array/hashes has been set'
fi
Pour ksh93
, zsh
et bash
4.4 ou supérieur, il y a aussi:
if typeset -p var 2> /dev/null | grep -q '^'; then
echo '$var exists'
fi
Qui rapportera les variables qui ont été définies ou déclarées.
Comme mentionné dans la réponse sur DONC , voici un moyen de vérifier:
if [ -z ${somevar+x} ]; then echo "somevar is unset"; else echo "somevar is set to '$somevar'"; fi
où $ {somevar + x} est une extension de paramètre qui prend la valeur null si var n'est pas définie et remplace la chaîne "x" sinon.
En utilisant -n
, comme suggéré par l'autre réponse, ne vérifiera que si la variable contient une chaîne vide. Il ne vérifiera pas son existence.
POSIX:
! (: "${somevar?}") 2>/dev/null && echo somevar unset
ou vous pouvez laisser votre Shell afficher le message pour vous:
(: "${somevar?}")
zsh: somevar: parameter not set
if set|grep '^somevar=' >/dev/null;then
echo "somevar exists"
else
echo "does not exist"
fi
printf ${var+'$var exists!\n'}
... n'imprimera rien du tout quand ce n'est pas le cas. Ou...
printf $"var does%${var+.}s exist%c\n" \ not !
... vous dira de toute façon.
vous pouvez utiliser la valeur de retour d'un test pour développer dynamiquement la chaîne de format appropriée à votre condition:
[ "${var+1}" ]
printf $"var does%.$?0s exist%c\n" \ not !
Vous pouvez également faire échouer printf
sur la base d'une substitution ...
printf $"var does%${var+.}s exist%c\n%.${var+b}d" \
\ not ! \\c >&"$((2${var+-1}))" 2>/dev/null
... qui imprime $var does not exist!
vers stderr et retourne autre que 0 lorsque $var
n'est pas défini, mais affiche $var does exist!
à stdout et renvoie 0 lorsque $var
est défini.
Cette ligne simple fonctionne (et fonctionne sur la plupart des shells POSIX):
${var+"false"} && echo "var is unset"
Ou, sous une forme plus longue:
unset var
if ${var+"false"}
then
echo "var is unset"
fi
L'expansion est:
Le ${var+"false"}
l'expansion se développe en "null" ou en "false".
Ensuite, "rien" ou le "faux" est exécuté et le code de sortie est défini.
Il n'est pas nécessaire d'appeler la commande test
([
ou [[
) car la valeur de sortie est définie par (l'exécution de) l'expansion elle-même.
bash fonction qui fonctionne pour les types scalaire et tablea:
has_declare() { # check if variable is set at all
local "$@" # inject 'name' argument in local scope
&>/dev/null declare -p "$name" # return 0 when var is present
}
if has_declare name="vars_name" ; then
echo "variable present: vars_name=$vars_name"
fi
La pure façon Shell:
[ "${var+1}" ] || echo "The variable has not been set"
Script de test:
#!/bin/sh
echo "Test 1, var has not yet been created"
[ "${var+1}" ] || echo "The variable has not been set"
echo "Test 2, var=1"
var=1
[ "${var+1}" ] || echo "The variable has not been set"
echo "Test 3, var="
var=
[ "${var+1}" ] || echo "The variable has not been set"
echo "Test 4, unset var"
unset var
[ "${var+1}" ] || echo "The variable has not been set"
echo "Done"
Résultats:
Test 1, var has not yet been created
The variable has not been set
Test 2, var=1
Test 3, var=
Test 4, unset var
The variable has not been set
Done
Avec bash 4.4.19, ce qui suit a fonctionné pour moi. Voici un exemple complet
$export MAGENTO_DB_Host="anyvalue"
#!/bin/bash
if [ -z "$MAGENTO_DB_Host" ]; then
echo "Magento variable not set"
else
echo $MAGENTO_DB_Host
fi
$array=()
En plus de @ Gilles's réponse
case " ${!foobar*} " in *" foobar "*) echo "foobar is declared";; *) echo "foobar is not declared";; esac
- dont je n'ai pas trouvé le moyen de l'encapsuler dans une fonction - je voudrais ajouter une version simple, qui est en partie basée sur Richard Hansen 's réponse , mais résout également l'écueil qui se produit avec une array=()
vide:
# The first parameter needs to be the name of the variable to be checked.
# (See example below)
var_is_declared() {
{ [[ -n ${!1+anything} ]] || declare -p $1 &>/dev/null;}
}
var_is_unset() {
{ [[ -z ${!1+anything} ]] && ! declare -p $1 &>/dev/null;}
}
$1
Contient le nom d'une $array=()
vide, l'appel à déclarer ferait en sorte d'obtenir le bon résultat
Avec le code suivant, les fonctions peuvent être testées:
( # start a subshell to encapsulate functions/vars for easy copy-paste into the terminal
# do not use this extra parenthesis () in a script!
var_is_declared() {
{ [[ -n ${!1+anything} ]] || declare -p $1 &>/dev/null;}
}
var_is_unset() {
{ [[ -z ${!1+anything} ]] && ! declare -p $1 &>/dev/null;}
}
:; echo -n 'a; '; var_is_declared a && echo "# is declared" || echo "# is not declared"
a=; echo -n 'a=; '; var_is_declared a && echo "# is declared" || echo "# is not declared"
a="sd"; echo -n 'a="sd"; '; var_is_declared a && echo "# is declared" || echo "# is not declared"
a=(); echo -n 'a=(); '; var_is_declared a && echo "# is declared" || echo "# is not declared"
a=(""); echo -n 'a=(""); '; var_is_declared a && echo "# is declared" || echo "# is not declared"
unset a; echo -n 'unset a; '; var_is_declared a && echo "# is declared" || echo "# is not declared"
echo ;
:; echo -n 'a; '; var_is_unset a && echo "# is unset" || echo "# is not unset"
a=; echo -n 'a=; '; var_is_unset a && echo "# is unset" || echo "# is not unset"
a="foo"; echo -n 'a="foo"; '; var_is_unset a && echo "# is unset" || echo "# is not unset"
a=(); echo -n 'a=(); '; var_is_unset a && echo "# is unset" || echo "# is not unset"
a=(""); echo -n 'a=(""); '; var_is_unset a && echo "# is unset" || echo "# is not unset"
unset a; echo -n 'unset a; '; var_is_unset a && echo "# is unset" || echo "# is not unset"
)
Le script devrait retourner
a; # is not declared
a=; # is declared
a="foo"; # is declared
a=(); # is declared
a=(""); # is declared
unset a; # is not declared
a; # is unset
a=; # is not unset
a="foo"; # is not unset
a=(); # is not unset
a=(""); # is not unset
unset a; # is unset
Vous ne pouvez pas utiliser la commande if
pour vérifier l'existence de variables déclarées dans bash mais l'option -v
Existe dans la nouvelle bash, mais elle n'est pas portable et vous ne pouvez pas l'utiliser dans les anciennes bash
versions. Parce que lorsque vous utilisez une variable si elle n'existe pas, elle naîtra en même temps.
Par exemple. Imaginez que je n'ai pas utilisé ou assigné de valeur à la variable MYTEST
, mais lorsque vous utilisez la commande echo, cela ne vous montre rien! Ou si vous utilisez if [ -z $MYTEST ]
, Il n'a retourné aucune valeur! Il n'a pas renvoyé un autre état de sortie, ce qui vous indique que cette variable n'existe pas!
Vous avez maintenant deux solutions (sans l'option -v
):
declare
.set
.Par exemple:
MYTEST=2
set | grep MYTEST
declare | grep MYTEST
Mais malheureusement, ces commandes vous montrent également les fonctions chargées en mémoire! Vous pouvez utiliser la commande declare -p | grep -q MYTEST ; echo $?
Pour un résultat plus net.