Pour les versions Bash antérieures à "GNU bash, Version 4.2", existe-t-il des alternatives équivalentes pour l'option -v
de la command test
? Par exemple:
shopt -os nounset test -v foobar && echo foo || echo bar # Output: bar foobar= test -v foobar && echo foo || echo bar # Output: foo
Portable à tous les obus POSIX:
if [ -n "${foobar+1}" ]; then echo "foobar is defined" else echo "foobar is not defined" fi
Faites que ${foobar:+1}
si vous voulez traiter foobar
la même manière, qu'elle soit vide ou non définie. Vous pouvez également utiliser ${foobar-}
pour get une string vide lorsque foobar
est indéfini et la valeur de foobar
cas contraire (ou mettre une autre valeur par défaut après le -
).
Dans ksh, si foobar
est déclaré mais non défini, comme dans typeset -a foobar
, alors ${foobar+1}
s'étend à la string vide.
Zsh n'a pas de variables déclarées mais pas définies: typeset -a foobar
crée un tableau vide.
En bash, les arrays se comportent de manière différente et surprenante. ${a+1}
ne prend que 1
si a
est un tableau non vide, par exemple
typeset -aa; echo ${a+1} # prints nothing e=(); echo ${e+1} # prints nothing! f=(''); echo ${f+1} # prints 1
Le même principe s'applique aux arrays associatifs: les variables masortingcielles sont traitées comme définies si elles ont un set d'index non vide.
Un moyen différent, bash-spécifique de tester si une variable de n'importe quel type a été définie est de vérifier s'il est répertorié dans ${! PREFIX *}
${! PREFIX *}
. Cela rapporte les arrays vides tels que définis, contrairement à ${foobar+1}
, mais rapporte les variables déclarées mais non assignées ( unset foobar; typeset -a foobar
) comme indéfini.
case " ${!foobar*} " in *" foobar "*) echo "foobar is defined";; *) echo "foobar is not defined";; esac
Cela équivaut à tester la valeur de return de typeset -p foobar
ou à declare -p foobar
, sauf que le typeset -p foobar
échoue sur les variables déclarées mais non assignées.
Dans bash, comme dans ksh, set -o nounset; typeset -a foobar; echo $foobar
set -o nounset; typeset -a foobar; echo $foobar
set -o nounset; typeset -a foobar; echo $foobar
triggers une erreur dans la tentative d'extension de la variable indéfinie foobar
. Contrairement à ksh, set -o nounset; foobar=(); echo $foobar
set -o nounset; foobar=(); echo $foobar
set -o nounset; foobar=(); echo $foobar
(ou echo "${foobar[@]}"
) triggers également une erreur.
Notez que dans toutes les situations décrites ici, ${foobar+1}
s'étend à la string vide si et seulement si $foobar
provoquerait une erreur sous set -o nounset
.
Pour résumer avec la réponse de Gilles, j'ai inventé les règles suivantes:
[[ -v foobar ]]
pour les variables dans la version Bash> = 4.2. declare -p foobar &>/dev/null
pour les variables de tableau dans la version Bash <4.2. (( ${foo[0]+1} ))
ou (( ${bar[foo]+1} ))
pour les indices des arrays indexés ( -a
) et keyed ( -A
). Les options 1 et 2 ne fonctionnent pas ici. J'utilise la même technique pour toutes les variables dans bash, et cela fonctionne, par exemple:
[ ${foobar} ] && echo "foobar is set" || echo "foobar is unset"
les sorties:
foobar is unset
tandis que
foobar=( "val" "val2" ) [ ${foobar} ] && echo "foobar is set" || echo "foobar is unset"
les sorties:
foobar is set