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?
Je pense que la réponse que vous recherchez est implicite (si non indiquée) par Vinkoréponse , bien qu'elle ne soit pas expliquée 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 avec:
if [ -z "$VAR" -a "${VAR+xxx}" = "xxx" ]; then echo VAR is set but empty; fi
Cependant, si vous lisez la documentation d'Autoconf, vous constaterez qu'il est déconseillé de combiner les termes avec '-a
'et 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 signifie pas qu'elles n'existaient pas (mais elles sont probablement extrêmement rares de nos jours, même si elles ne l'étaient pas auparavant).
Vous pouvez trouver les détails de ceux-ci, ainsi que d’autres Expansions des paramètres du shell , les test
ou [
commande et expressions conditionnelles dans le manuel Bash.
On m'a récemment demandé par courrier électronique à propos de cette réponse à 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
Est-ce que cela ne ferait pas la même chose?
if [ -z "${VAR}" ]; then echo VAR is not set at all; fi
Bonne question - la réponse est "Non, votre solution de remplacement 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
)
La sortie 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 le ${VAR=value}
et ${VAR:=value}
notations font. Idem pour ${VAR-value}
et ${VAR:-value}
, et ${VAR+value}
et ${VAR:+value}
, etc.
Comme Gili indique dans son réponse , si vous exécutez bash
avec le set -o nounset
, la réponse de base ci-dessus échoue avec unbound variable
. Il est facile d'y remédier:
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
Ou vous pouvez annuler le set -o nounset
option avec set +u
(set -u
étant équivalent à set -o nounset
).
~> 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 aussi pour les variables non définies. Pour distinguer entre un indéfini et un défini, vous utiliseriez les éléments énumérés ici ou, avec des explications plus claires, ici .
La manière 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 remplaçant la valeur par défaut par la valeur de votre choix et en utilisant directement l'extension, le cas échéant.
Guide de script avancé bash, 10.2. Paramètre Substitution:
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 était indéfinie, si isdefined = 1 la variable était définie
Cette façon de vérifier les variables est meilleure que la réponse ci-dessus car elle est plus élégante, lisible, et si votre bash Shell était configuré pour commettre une erreur lors de l’utilisation de variables non définies (set -u)
, le script se termine prématurément.
Autres choses utiles:
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 que j'ai utilisé ':' pour ne pas avoir le contenu de $ mystr exécuté en tant que commande au cas où il serait défini.
Un 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 qui fonctionne avec set -o nounset
activée). Cela fonctionne à peu près comme ça:
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 vérifier si une variable est définie serait:
[ -v mystr ]
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 ]
Correspondent à pas optionnel.
Astuces pour les utilisateurs de Vim
J'ai eu un script qui a eu plusieurs déclarations comme suit:
export VARIABLE_NAME="$SOME_OTHER_VARIABLE/path-part"
Mais je voulais qu’ils s’en remettent aux valeurs existantes. Alors je les ai 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 un 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 pertinentes, puis en tapant :
. La barre de commande 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 [email protected]
Les utilisateurs de Windows peuvent vouloir des fins de lignes différentes.
autre option: extension "list array index" :
$ unset foo
$ foo=
$ echo ${!foo[*]}
0
$ foo=bar
$ echo ${!foo[*]}
0
$ foo=(bar baz)
$ echo ${!foo[*]}
0 1
la seule fois que cela devient une chaîne vide, c'est quand 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 d'un script, ce qui entraînera une erreur si les variables ne sont pas déclarées dans le script. Le message que vous verriez est unbound variable
, mais comme d'autres le mentionnent, cela n'attrapera pas une chaîne vide ou une 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é expansion du signe dollar, qui commettrait une erreur avec parameter null or not set
.
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