Pour les versions de Bash antérieures à "GNU bash, version 4.2", existe-t-il des alternatives équivalentes pour l' -v
option de la test
commande? Par exemple:
shopt -os nounset
test -v foobar && echo foo || echo bar
# Output: bar
foobar=
test -v foobar && echo foo || echo bar
# Output: foo
-v
n'est pas une option pourtest
, mais un opérateur pour les expressions conditionnelles.option
à une commandetest -v
, unoperator
à unconditional expression
et ununary test primary
pour[ ]
. Ne mélangez pas la langue anglaise avec les définitions de shell.Réponses:
Portable sur tous les shells POSIX:
Faites cela
${foobar:+1}
si vous voulez traiter defoobar
la même manière, qu'il soit vide ou non défini. Vous pouvez également utiliser${foobar-}
pour obtenir une chaîne vide lorsquefoobar
est indéfini et la valeur defoobar
sinon (ou mettre toute autre valeur par défaut après le-
).Dans ksh, if
foobar
est déclaré mais non défini, comme danstypeset -a foobar
, puis se${foobar+1}
développe dans la chaîne vide.Zsh n'a pas de variables déclarées mais non définies:
typeset -a foobar
crée un tableau vide.En bash, les tableaux se comportent de manière différente et surprenante.
${a+1}
ne se développe que1
sia
est un tableau non vide, par exempleLe même principe s'applique aux tableaux associatifs: les variables de tableau sont traitées comme définies si elles ont un ensemble d'indices non vide.
Une manière différente, spécifique à bash, de tester si une variable de n'importe quel type a été définie consiste à vérifier si elle est répertoriée dans . Cela signale les tableaux vides tels que définis, contrairement à , mais signale les variables déclarées mais non affectées ( ) comme non définies.
${!PREFIX*}
${foobar+1}
unset foobar; typeset -a foobar
Cela revient à tester la valeur de retour de
typeset -p foobar
oudeclare -p foobar
, sauf qu'iltypeset -p foobar
échoue sur les variables déclarées mais non affectées.Dans bash, comme dans ksh,
set -o nounset; typeset -a foobar; echo $foobar
déclenche une erreur dans la tentative de développement de la variable non définiefoobar
. Contrairement à ksh,set -o nounset; foobar=(); echo $foobar
(ouecho "${foobar[@]}"
) déclenche également une erreur.Notez que dans toutes les situations décrites ici, se
${foobar+1}
développe dans la chaîne vide si et seulement si$foobar
provoquerait une erreur sousset -o nounset
.la source
echo "${foobar:+1}"
ne s'imprime pas1
si adeclare -a foobar
été précédemment émis etfoobar
est donc un tableau indexé.declare -p foobar
rapporte correctementdeclare -a foobar='()'
. Ne"${foobar:+1}"
fonctionne que pour les variables non matricielles?${foobar+1}
(sans le:
, j'ai inversé deux exemples dans ma réponse d'origine) est correct pour les tableaux en bash si votre définition de «défini» est «$foobar
fonctionnerait sousset -o nounset
». Si votre définition est différente, bash est un peu bizarre. Voir ma réponse mise à jour.0
index ni une clé n'est défini comme il est vrai poura=()
,${a+1}
ne renvoie correctement rien.defined
opérateur.Test
pourrait le faire ; ça ne peut pas être difficile ( euh ...)Pour résumer la réponse de Gilles, j'ai établi mes 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 tableaux indexés (-a
) et keyed (-A
) (declare
), respectivement. Les options 1 et 2 ne fonctionnent pas ici.la source
J'utilise la même technique pour toutes les variables en bash, et cela fonctionne, par exemple:
les sorties:
tandis que
les sorties:
la source
foobar=""
je ferai ensuite rapport de celafoobar is unset
. Non attends, je reprends ça. Vraiment ne teste que si le premier élément est vide ou non, donc cela ne semble être une bonne idée que si vous savez que la variable n'est PAS un tableau, et que vous ne vous souciez que du vide, pas de la définition.