web-dev-qa-db-fra.com

Comment vérifier si une variable existe dans une instruction 'if'?

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.

74
Interesting...

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

103
Chris Down

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.

28
Stéphane Chazelas

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.

10
shivams

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
4
cuonglm
if set|grep '^somevar=' >/dev/null;then
    echo "somevar exists"
else
    echo "does not exist"
fi
3
Mel
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.

2
mikeserv

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:

  • Si le var a une valeur (même null), false est remplacé
  • Si le var n'a "aucune valeur", alors "aucune valeur" (null) est remplacé.

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.

1
user79743

bash fonction qui fonctionne pour les types scalaire et tablea:

définition

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
}

invocation

if has_declare name="vars_name" ; then
   echo "variable present: vars_name=$vars_name"
fi
0
Andrei Pozolotin

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
0

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
0
Aftab Naveed

Fonction pour vérifier si la variable est déclarée/non définie

y compris vide $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;} 
}
  • En testant d'abord si la variable est (dé) définie, l'appel à déclarer peut être évité, si ce n'est pas nécessaire.
  • Si toutefois $1 Contient le nom d'une $array=() vide, l'appel à déclarer ferait en sorte d'obtenir le bon résultat
  • Il n'y a jamais beaucoup de données transmises à/dev/null car declare n'est appelé que si la variable est non définie ou un tableau vide.


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
0
Martin Rüegg

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):

  1. Utilisation de la commande declare.
  2. Utilisation de la commande 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.

0
Sepahrad Salour