En utilisant:
set -o nounset
Avoir un tableau indexé comme:
myArray=( "red" "black" "blue" )
Quel est le moyen le plus court pour vérifier si l'élément 1 est défini?
J'utilise parfois ce qui suit:test "${#myArray[@]}" -gt "1" && echo "1 exists" || echo "1 doesn't exist"
Je voudrais savoir s'il y en a un préféré.
Comment gérer les index non consécutifs?
myArray=() myArray[12]="red" myArray[51]="black" myArray[129]="blue"
Comment vérifier rapidement ce qui
51
est déjà défini par exemple?Comment gérer les tableaux associatifs?
declare -A myArray myArray["key1"]="red" myArray["key2"]="black" myArray["key3"]="blue"
Comment vérifier rapidement qui
key2
est déjà utilisé par exemple?
+abc
,[ ${array[key]} ]
sera évalué à faux si l'élément est bien défini mais à une valeur vide, donc il teste en fait la valeur non vide plutôt que l'existence de la clé.+abc
également échoué lorsquearray[key]
n'est pas défini etset -u
est effectif.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 positionnés (même si ce dernier a une valeur vide) et foo [quux] ne l'est pas.
la source
set -u
, pourquoi[[ -v "${foo[bar]}" ]]
produit-il une erreur de variable non liée si ellebar
n'existe pas dans le dictionnaire? Fonctionne bien sans le${}
; Je suis juste habitué à l'utiliser pour tout par défaut."${foo[bar]}"
évalue d'abord la variable de tableau, donc la[[ -v
commande teste une variable avec le nom de cette valeurNouvelle réponse
À partir de la version 4.2 de frapper(et plus récent), il existe une nouvelle
-v
option pour latest
commande intégrée .array=([12]="red" [51]="black" [129]="blue") for i in 10 12 30 {50..52} {128..131};do if [ -v array[i] ];then echo "Variable 'array[$i]' is defined" else echo "Variable 'array[$i]' not exist" fi done Variable 'array[10]' not exist Variable 'array[12]' is defined Variable 'array[30]' not exist Variable 'array[50]' not exist Variable 'array[51]' is defined Variable 'array[52]' not exist Variable 'array[128]' not exist Variable 'array[129]' is defined Variable 'array[130]' not exist Variable 'array[131]' not exist
Cela fonctionne avec les tableaux associatifs de la même manière:
declare -A aArray=([foo]="bar" [bar]="baz" [baz]=$'Hello world\041') for i in alpha bar baz dummy foo test;do if [ -v aArray[$i] ];then echo "Variable 'aArray[$i]' is defined" else echo "Variable 'aArray[$i]' not exist" fi done Variable 'aArray[alpha]' not exist Variable 'aArray[bar]' is defined Variable 'aArray[baz]' is defined Variable 'aArray[dummy]' not exist Variable 'aArray[foo]' is defined Variable 'aArray[test]' not exist
Avec une petite différence:
dans les tableaux réguliers, la variable entre crochets (
[i]
) est un entier, donc le symbole dollar ($
) n'est pas requis, mais pour les tableaux associatifs, comme la clé est un mot,$
est requis ([$i]
)!Ancienne réponse pour frapper avant V4.2
Malheureusement, bash ne laisse aucun moyen de faire la différence entre variable vide et une variable indéfinie .
Mais il y a quelques 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 donne pas de réponse)
Et pour le tableau associatif, vous pouvez utiliser le même:
$ 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 de printf | grep comme pure bash ), et pourquoi pas, construire checkIfExist () comme une 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 bash getIfExist 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
la source
bash 4.2.46
. Fonctionne dessusbash 4.4.12
.-v
optiontest
ougetIfExist
fonction?-v
ne fonctionne pas sur les tableaux sur mon CentOS 7.7.1908 avec bash 4.2.46. Le code de votre premier bloc de code s'imprimenot exist
dans tous les cas sous ce bash. (Également essayé à la[$i]
place de[i]
, aucune différence)testé dans la version 4.3.39 (1) de bash
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
la source
+
expansion des paramètres pour remplacer une valeur vide par un espace réservé comme un trait de soulignement. Par exempledeclare -A a[x]=;[[ ${a[x]} ]];echo $?
imprime1
, maisdeclare -A a[x]=;[[ ${a[x]+_} ]];echo $?
imprime0
.Qu'en est-il d'un
-z
test et du:-
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
la source
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épendez de ce que vous voulez réaliser:
la 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
la valeur existe :
if grep -qe "<search>" <(echo "${ASSOC_ARRAY[@]}"); then echo value is present; fi
la valeur n'existe pas :
if ! grep -qe "<search>" <(echo "${ASSOC_ARRAY[@]}"); then echo value not present; fi
la source
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)
la source