Question

Si je veux vérifier la chaîne nulle, je le ferais

[ -z $mystr ]

mais que faire si je veux vérifier si la variable a été définie? Ou n'y a-t-il pas de distinction dans les scripts bash?

Était-ce utile?

La solution

Je pense que la réponse que vous recherchez est implicite (si non spécifiée) par Vinko répondre , bien que cela ne soit pas expliqué simplement. Pour distinguer si VAR est défini mais vide ou non défini, vous pouvez utiliser:

if [ -z "${VAR+xxx}" ]; then echo VAR is not set at all; fi
if [ -z "$VAR" ] && [ "${VAR+xxx}" = "xxx" ]; then echo VAR is set but empty; fi

Vous pouvez probablement combiner les deux tests de la deuxième ligne en un seul avec:

if [ -z "$VAR" -a "${VAR+xxx}" = "xxx" ]; then echo VAR is set but empty; fi

Toutefois, si vous lisez la documentation d'Autoconf, vous constaterez qu'il est déconseillé de combiner les termes avec '-a' et vous recommande d'utiliser des tests simples distincts combinés avec &&. Je n'ai pas rencontré de système présentant un problème. cela ne veut pas dire qu'ils n'existaient pas auparavant (mais ils sont probablement extrêmement rares de nos jours, même s'ils ne l'étaient plus dans un passé lointain).

Vous pouvez trouver les détails de ceux-ci, et d'autres extensions des paramètres du shell , test ou < => commande et expressions conditionnelles dans le manuel Bash.

On m'a récemment demandé par courrier électronique à propos de cette réponse avec la question:

  

Vous utilisez deux tests et je comprends bien le second, mais pas le premier. Plus précisément, je ne comprends pas la nécessité d’une expansion variable

if [ -z "${VAR+xxx}" ]; then echo VAR is not set at all; fi
     

Cela ne ferait-il pas le même?

if [ -z "${VAR}" ]; then echo VAR is not set at all; fi

Bonne question - la réponse est non, votre alternative la plus simple ne fait pas la même chose.

Supposons que j'écrive ceci avant votre test:

VAR=

Votre test indiquera & "; VAR n'est pas défini du tout &" ;, mais le mien dira (par implication, car il ne fait écho à rien) & "; VAR est défini mais sa valeur peut être vide. & Essayez ce script:

(
unset VAR
if [ -z "${VAR+xxx}" ]; then echo JL:1 VAR is not set at all; fi
if [ -z "${VAR}" ];     then echo MP:1 VAR is not set at all; fi
VAR=
if [ -z "${VAR+xxx}" ]; then echo JL:2 VAR is not set at all; fi
if [ -z "${VAR}" ];     then echo MP:2 VAR is not set at all; fi
)

Le résultat est:

JL:1 VAR is not set at all
MP:1 VAR is not set at all
MP:2 VAR is not set at all

Dans la deuxième paire de tests, la variable est définie, mais sa valeur est vide. C’est la distinction que font les notations [ et ${VAR=value}. Idem pour ${VAR:=value} et ${VAR-value}, et ${VAR:-value} et ${VAR+value}, etc.>.

Comme indiqué par Gili dans son répondre , si vous exécutez ${VAR:+value} avec l'option bash, la réponse de base ci-dessus échoue avec set -o nounset. On y remédie facilement:

if [ -z "${VAR+xxx}" ]; then echo VAR is not set at all; fi
if [ -z "${VAR-}" ] && [ "${VAR+xxx}" = "xxx" ]; then echo VAR is set but empty; fi

Vous pouvez également annuler l'option unbound variable avec set +u (set -u équivalent à <=>).

Autres conseils

~> if [ -z $FOO ]; then echo "EMPTY"; fi
EMPTY
~> FOO=""
~> if [ -z $FOO ]; then echo "EMPTY"; fi
EMPTY
~> FOO="a"
~> if [ -z $FOO ]; then echo "EMPTY"; fi
~> 

-z fonctionne également pour les variables non définies. Pour faire la distinction entre un indéfini et un défini, vous utiliseriez les éléments répertoriés ici ou avec des explications plus claires. , ici .

La méthode la plus propre consiste à utiliser l’expansion comme dans ces exemples. Pour obtenir toutes vos options, consultez la section Extension de paramètre du manuel.

Autre mot:

~$ unset FOO
~$ if test ${FOO+defined}; then echo "DEFINED"; fi
~$ FOO=""
~$ if test ${FOO+defined}; then echo "DEFINED"; fi
DEFINED

Valeur par défaut:

~$ FOO=""
~$ if test "${FOO-default value}" ; then echo "UNDEFINED"; fi
~$ unset FOO
~$ if test "${FOO-default value}" ; then echo "UNDEFINED"; fi
UNDEFINED

Bien sûr, vous utiliseriez l’une de ces manières différemment, en plaçant la valeur souhaitée au lieu de "valeur par défaut" et en utilisant directement le développement, le cas échéant.

Guide de script avancé bash, 10.2. Paramètre Substitution:

  • $ {var + blahblah}: si var est défini, 'blahblah' remplace le mot expression, sinon null est substitué
  • $ {var-blahblah}: si var est défini, il est lui-même substitué, sinon "blahblah" est substitué
  • $ {var? blahblah}: si var est défini, il est substitué, sinon le La fonction existe avec "blahblah" comme message d'erreur.


pour baser la logique de votre programme sur le fait que la variable $ mystr soit définie ou non, vous pouvez procéder comme suit:

isdefined=0
${mystr+ export isdefined=1}

maintenant, si isdefined = 0 alors la variable n'était pas définie, si isdefined = 1 la variable était définie

Cette méthode de vérification des variables est préférable à la réponse ci-dessus car elle est plus élégante, lisible et si votre shell bash était configuré pour commettre une erreur lors de l'utilisation de variables non définies (set -u), le script se terminera prématurément.


Autres éléments utiles:

pour avoir une valeur par défaut de 7 assignée à $ mystr si elle était indéfinie, et la laisser intacte sinon:

mystr=${mystr- 7}

pour imprimer un message d'erreur et quitter la fonction si la variable n'est pas définie:

: ${mystr? not defined}

Attention ici, j'ai utilisé ':' pour ne pas avoir le contenu de $ mystr exécuté en tant que commande au cas où il serait défini.

Résumé des tests.

[ -n "$var" ] && echo "var is set and not empty"
[ -z "$var" ] && echo "var is unset or empty"
[ "${var+x}" = "x" ] && echo "var is set"  # may or may not be empty
[ -n "${var+x}" ] && echo "var is set"  # may or may not be empty
[ -z "${var+x}" ] && echo "var is unset"
[ -z "${var-x}" ] && echo "var is set and empty"

https://stackoverflow.com/a/9824943/14731 contient une meilleure réponse (une réponse plus lisible). et fonctionne avec set -o nounset activé). Cela fonctionne à peu près comme ceci:

if [ -n "${VAR-}" ]; then
    echo "VAR is set and is not empty"
elif [ "${VAR+DEFINED_BUT_EMPTY}" = "DEFINED_BUT_EMPTY" ]; then
    echo "VAR is set, but empty"
else
    echo "VAR is not set"
fi

Le moyen explicite de rechercher une variable en cours de définition serait:

[ -v mystr ]

une autre option: la liste " indices de tableau " extension :

$ unset foo
$ foo=
$ echo ${!foo[*]}
0
$ foo=bar
$ echo ${!foo[*]}
0
$ foo=(bar baz)
$ echo ${!foo[*]}
0 1

le seul cas où la chaîne vide se développe est lorsque foo n'est pas défini, vous pouvez donc le vérifier avec la chaîne conditionnelle:

$ unset foo
$ [[ ${!foo[*]} ]]; echo $?
1
$ foo=
$ [[ ${!foo[*]} ]]; echo $?
0
$ foo=bar
$ [[ ${!foo[*]} ]]; echo $?
0
$ foo=(bar baz)
$ [[ ${!foo[*]} ]]; echo $?
0

devrait être disponible dans toutes les versions de bash > = 3.0

ne pas jeter ce vélo encore plus loin, mais je voulais ajouter

shopt -s -o nounset

est quelque chose que vous pouvez ajouter en haut du script, ce qui entraînera une erreur si les variables ne sont déclarées nulle part dans le script. Le message que vous voyez est unbound variable, mais comme d’autres le mentionnent, il n’accroche pas de chaîne vide ni de valeur NULL. Pour vous assurer que chaque valeur individuelle n'est pas vide, nous pouvons tester une variable car elle est développée avec ${mystr:?}, également appelée expansion du signe dollar, ce qui entraînerait une erreur avec parameter null or not set.

Le Manuel de référence de Bash est une source d’information faisant autorité sur bash.

Voici un exemple de test d'une variable pour voir si elle existe:

if [ -z "$PS1" ]; then
        echo This shell is not interactive
else
        echo This shell is interactive
fi

(De section 6.3.2 .)

Notez que les espaces après l'ouverture [ et avant la ] ne sont pas facultatifs .

Conseils pour les utilisateurs de Vim

J'ai eu un script qui avait plusieurs déclarations comme suit:

export VARIABLE_NAME="$SOME_OTHER_VARIABLE/path-part"

Mais je voulais qu’ils s’en remettent aux valeurs existantes. Je les ai donc ré-écrites pour ressembler à ceci:

if [ -z "$VARIABLE_NAME" ]; then
        export VARIABLE_NAME="$SOME_OTHER_VARIABLE/path-part"
fi

J'ai été capable d'automatiser cela dans vim en utilisant une regex rapide:

s/\vexport ([A-Z_]+)\=("[^"]+")\n/if [ -z "$\1" ]; then\r  export \1=\2\rfi\r/gc

Ceci peut être appliqué en sélectionnant visuellement les lignes appropriées, puis en tapant :. La barre de commandes pré-remplit avec :'<,'>. Collez la commande ci-dessus et appuyez sur Entrée.

Testé sur cette version de Vim:

VIM - Vi IMproved 7.3 (2010 Aug 15, compiled Aug 22 2015 15:38:58)
Compiled by root@apple.com

Les utilisateurs de Windows peuvent vouloir des fins de ligne différentes.

Voici ce que je pense être un moyen beaucoup plus clair de vérifier si une variable est définie:

var_defined() {
    local var_name=$1
    set | grep "^${var_name}=" 1>/dev/null
    return $?
}

Utilisez-le comme suit:

if var_defined foo; then
    echo "foo is defined"
else
    echo "foo is not defined"
fi

call set set sans aucun argument .. il affiche tous les vars définis ..
les derniers de la liste seraient ceux définis dans votre script.
afin que vous puissiez diriger sa sortie vers quelque chose qui pourrait comprendre ce que les choses sont définies et ce qui ne l'est pas

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top