En utilisant:
set -o nounset
1) Avoir un tableau indexé comme:
myArray=( "red" "black" "blue" )
Quel est le moyen le plus rapide de vérifier si l'élément 1 est défini?
J'utilise parfois les éléments suivants:
test "${#myArray[@]}" -gt "1" && echo "1 exists" || echo "1 doesn't exist"
J'aimerais savoir s'il y en a un préféré.
2) Comment traiter les index non consécutifs?
myArray=()
myArray[12]="red"
myArray[51]="black"
myArray[129]="blue"
Comment vérifier rapidement que '51' est déjà défini, par exemple?
3) Comment traiter les tableaux associatifs?
declare -A myArray
myArray["key1"]="red"
myArray["key2"]="black"
myArray["key3"]="blue"
Comment vérifier rapidement que 'key2' est déjà utilisé par exemple?
Merci
ÉDITÉ
La manière la plus simple me semble:
if test "${myArray['key_or_index']+isset}"
then
echo "yes"
else
echo "no"
fi;
Cela fonctionne à la fois pour les tableaux indexés et associatifs. Aucune erreur affichée avec set -o nounset.
Merci à doubleDown pour le heads-up.
Pour vérifier si l'élément est défini (s'applique à la fois aux tableaux indexés et associatifs)
[ ${array[key]+abc} ] && echo "exists"
Fondamentalement ce que ${array[key]+abc}
fait est
array[key]
est défini, retourne abc
array[key]
n'est pas défini, ne renvoie rienVoir Expansion des paramètres dans le manuel de Bash et la petite note
si les deux points sont omis, l'opérateur ne vérifie que l'existence [de paramètre ]
Cette réponse est en réalité adaptée des réponses pour ceci SO question: Comment savoir si une chaîne n'est pas définie dans un script shell bash) ?
Une fonction wrapper:
exists(){
if [ "$2" != in ]; then
echo "Incorrect usage."
echo "Correct usage: exists {key} in {array}"
return
fi
eval '[ ${'$3'[$1]+muahaha} ]'
}
Par exemple
if ! exists key in array; then echo "No such array element"; fi
De man bash , expressions conditionnelles:
-v varname
True if the Shell variable varname is set (has been assigned a value).
exemple:
declare -A foo
foo[bar]="this is bar"
foo[baz]=""
if [[ -v "foo[bar]" ]] ; then
echo "foo[bar] is set"
fi
if [[ -v "foo[baz]" ]] ; then
echo "foo[baz] is set"
fi
if [[ -v "foo[quux]" ]] ; then
echo "foo[quux] is set"
fi
Cela montrera que foo [bar] et foo [baz] sont tous deux définis (même si cette dernière est définie sur une valeur vide) et que foo [quux] ne l’est pas.
Malheureusement, bash ne donne aucun moyen de faire la différence entre vide et variable indéfinie .
Mais il y a des moyens:
$ array=()
$ array[12]="red"
$ array[51]="black"
$ array[129]="blue"
$ echo ${array[@]}
red black blue
$ echo ${!array[@]}
12 51 129
$ echo "${#array[@]}"
3
$ printf "%s\n" ${!array[@]}|grep -q ^51$ && echo 51 exist
51 exist
$ printf "%s\n" ${!array[@]}|grep -q ^52$ && echo 52 exist
(ne pas répondre)
Et pour un tableau associatif, vous pouvez utiliser la même chose:
$ unset array
$ declare -A array
$ array["key1"]="red"
$ array["key2"]="black"
$ array["key3"]="blue"
$ echo ${array[@]}
blue black red
$ echo ${!array[@]}
key3 key2 key1
$ echo ${#array[@]}
3
$ set | grep ^array=
array=([key3]="blue" [key2]="black" [key1]="red" )
$ printf "%s\n" ${!array[@]}|grep -q ^key2$ && echo key2 exist || echo key2 not exist
key2 exist
$ printf "%s\n" ${!array[@]}|grep -q ^key5$ && echo key5 exist || echo key5 not exist
key5 not exist
Vous pouvez faire le travail sans avoir besoin d’outils externes (pas printf | grep as pure bash ), et pourquoi pas, build checkIfExist ( ) en tant que nouvelle fonction bash:
$ checkIfExist() {
eval 'local keys=${!'$1'[@]}';
eval "case '$2' in
${keys// /|}) return 0 ;;
* ) return 1 ;;
esac";
}
$ checkIfExist array key2 && echo exist || echo don\'t
exist
$ checkIfExist array key5 && echo exist || echo don\'t
don't
ou même créer une nouvelle fonction getIfExist bash qui renvoie la valeur souhaitée et quitte avec un code de résultat faux si la valeur souhaitée n'existe pas:
$ getIfExist() {
eval 'local keys=${!'$1'[@]}';
eval "case '$2' in
${keys// /|}) echo \${$1[$2]};return 0 ;;
* ) return 1 ;;
esac";
}
$ getIfExist array key1
red
$ echo $?
0
$ # now with an empty defined value
$ array["key4"]=""
$ getIfExist array key4
$ echo $?
0
$ getIfExist array key5
$ echo $?
1
testé en version 4.3.39 (1)
declare -A fmap
fmap['foo']="boo"
key='foo'
# should echo foo is set to 'boo'
if [[ -z "${fmap[${key}]}" ]]; then echo "$key is unset in fmap"; else echo "${key} is set to '${fmap[${key}]}'"; fi
key='blah'
# should echo blah is unset in fmap
if [[ -z "${fmap[${key}]}" ]]; then echo "$key is unset in fmap"; else echo "${key} is set to '${fmap[${key}]}'"; fi
J'ai écrit une fonction pour vérifier si une clé existe dans un tableau dans Bash:
# Check if array key exists
# Usage: array_key_exists $array_name $key
# Returns: 0 = key exists, 1 = key does NOT exist
function array_key_exists() {
local _array_name="$1"
local _key="$2"
local _cmd='echo ${!'$_array_name'[@]}'
local _array_keys=($(eval $_cmd))
local _key_exists=$(echo " ${_array_keys[@]} " | grep " $_key " &>/dev/null; echo $?)
[[ "$_key_exists" = "0" ]] && return 0 || return 1
}
Exemple
declare -A my_array
my_array['foo']="bar"
if [[ "$(array_key_exists 'my_array' 'foo'; echo $?)" = "0" ]]; then
echo "OK"
else
echo "ERROR"
fi
Testé avec GNU bash, version 4.1.5 (1) -release (i486-pc-linux-gnu)
C'est le moyen le plus simple que j'ai trouvé pour les scripts.
<search>
est la chaîne que vous voulez trouver, ASSOC_ARRAY
le nom de la variable contenant votre tableau associatif.
Dépend de ce que vous voulez réaliser:
clé existe :
if grep -qe "<search>" <(echo "${!ASSOC_ARRAY[@]}"); then echo key is present; fi
la clé n'existe pas :
if ! grep -qe "<search>" <(echo "${!ASSOC_ARRAY[@]}"); then echo key not present; fi
valeur existe :
if grep -qe "<search>" <(echo "${ASSOC_ARRAY[@]}"); then echo value is present; fi
la valeur existe pas :
if ! grep -qe "<search>" <(echo "${ASSOC_ARRAY[@]}"); then echo value not present; fi
Qu'en est-il d'un -z
test et le :-
opérateur?
Par exemple, ce script:
#!/usr/bin/env bash
set -e
set -u
declare -A sample
sample["ABC"]=2
sample["DEF"]=3
if [[ ! -z "${sample['ABC']:-}" ]]; then
echo "ABC is set"
fi
if [[ ! -z "${sample['DEF']:-}" ]]; then
echo "DEF is set"
fi
if [[ ! -z "${sample['GHI']:-}" ]]; then
echo "GHI is set"
fi
Impressions:
ABC is set
DEF is set