Facile à vérifier, pour un indice ou d'une clé dans un tableau?

utilisant:

set -o nounset

1) ayant 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 le texte suivant:

test "${#myArray[@]}" -gt "1" && echo "1 exists" || echo "1 doesn't exist"

j'aimerais savoir s'il y en a une préférée.



2) Comment traiter les indices non consécutifs?

myArray=()
myArray[12]="red"
myArray[51]="black"
myArray[129]="blue"

Comment faire vérifiez 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 pour les deux tableaux indexés et associatifs. Aucune erreur n'est affichée avec set-o nounset.

Merci à doubleDown pour le headup.

58
demandé sur Luca Borrione 2012-11-04 18:57:04

6 réponses

Pour vérifier si l'élément est défini (s'applique à la fois indexé et tableau associatif)

[ ${array[key]+abc} ] && echo "exists"

essentiellement ce que ${array[key]+abc} fait est

  • si array[key] est défini, retourner abc
  • si array[key] n'est pas défini, renvoyer rien


Référence:
  1. Voir Paramètre Expansion dans le manuel de Bash et la petite note

    si le deux-points est omis, l'opérateur ne vérifie que l'existence [du paramètre 1519300920"]

  2. cette réponse est en fait adaptée des réponses à cette question SO: Comment dire si une chaîne de caractères n'est pas définie dans un script shell bash ?


Une fonction wrapper:

exists(){
  if [ "" != in ]; then
    echo "Incorrect usage."
    echo "Correct usage: exists {key} in {array}"
    return
  fi   
  eval '[ ${''[]+muahaha} ]'  
}

par exemple

if ! exists key in array; then echo "No such array element"; fi 
89
répondu doubleDown 2017-05-23 12:10:31

malheureusement, bash ne donne aucun moyen de faire la différence entre vide et Non défini variable.

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

(donnez pas de réponse)

et pour associative array, 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 pourraient faire le travail sans avoir besoin d'outils externes (pas de printf|grep pur bash ), et pourquoi pas, construire checkIfExist () comme une nouvelle fonction de bash:

$ checkIfExist() {
    eval 'local keys=${!''[@]}';
    eval "case '' 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 un nouveau getIfExist bash fonction qui retournent la valeur désirée et la sortie avec le résultat faux-code si la valeur désirée n'existe pas:

$ getIfExist() {
    eval 'local keys=${!''[@]}';
    eval "case '' in
        ${keys// /|}) echo ${[]};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
7
répondu F. Hauri 2013-03-04 19:39:06

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 définis (même si ce dernier est défini à une valeur vide) et que foo[quux] ne l'est pas.

5
répondu Vineet 2017-07-29 05:00:27

testé dans bash 4.3.39 (1) - release

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
4
répondu gdoubleod 2015-11-13 03:28:48

C'est le moyen le plus facile que j'ai trouvé pour les scripts.

<search> est la corde que vous voulez trouver, ASSOC_ARRAY le nom de la variable contenant votre tableau associatif.

dépend de ce que vous voulez accomplir:

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
1
répondu sjas 2016-08-15 14:58:36

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=""
    local _key=""
    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)

1
répondu Lucas Stad 2017-02-22 11:04:47