117 votes

Le moyen le plus simple de vérifier un index ou une clé dans un tableau ?

Utilisation :

set -o nounset
  1. Avoir un tableau indexé comme :

    myArray=( "red" "black" "blue" )

    Quel est le moyen le plus court de 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"

    J'aimerais savoir s'il y a une préférence.

  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à fixé 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 ?

2voto

Lawrence Kirby Points 21

Je répète ce qu'a dit Thamme :

[[ ${array[key]+Y} ]] && echo Y || echo N

Cela permet de vérifier si l'élément de la variable/du tableau existe, y compris s'il est défini par une valeur nulle. Cela fonctionne avec un plus grand nombre de versions de bash que -v et ne semble pas sensible à des choses comme set -u. Si vous voyez un "mauvais indice de tableau" en utilisant cette méthode, veuillez poster un exemple.

1voto

sjas Points 3175

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

<search> est la chaîne de caractères que vous voulez trouver, ASSOC_ARRAY le nom de la variable contenant votre tableau associatif.

Tout dépend de ce que vous voulez obtenir :

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

valeur existe pas :

if ! grep -qe "<search>" <(echo "${ASSOC_ARRAY[@]}"); then echo value not present; fi

1voto

Lucas Stad Points 11

J'ai écrit une fonction pour vérifier si une clé existe dans un tableau en 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)

1voto

Anthony Rutledge Points 280

Pour tous les peuples du temps, une fois pour toutes.

Il y a un long chemin de "code propre", et il y a un chemin plus court, plus concis, centré sur bash.

$1 = L'index ou la clé que vous recherchez.

$2 = Le tableau / la carte transmis par référence .

function hasKey ()
{
    local -r needle="${1:?}"
    local -nr haystack=${2:?}

    for key in "${!haystack[@]}"; do
        if [[ $key == $needle ]] ;
            return 0
        fi
    done

    return 1
}

Une recherche linéaire peut être remplacée par une recherche binaire, qui serait plus performante avec des ensembles de données plus importants. Il suffit de compter et de trier les clés dans un premier temps, puis de diviser la meule de foin en deux de manière binaire au fur et à mesure que l'on se rapproche de la réponse.

Maintenant, pour les puristes qui se disent "Non, je veux la version la plus performante parce que je pourrais avoir à gérer de grands tableaux en bash", voyons une solution plus centrée sur bash, mais qui conserve un code propre et la flexibilité de gérer des tableaux ou des cartes.

function hasKey ()
{
    local -r needle="${1:?}"
    local -nr haystack=${2:?}

    [ -n ${haystack["$needle"]+found} ]
}

La línea [ -n ${haystack["$needle"]+found} ] utilise le ${parameter+word} de l'expansion des variables de bash, et non la ${parameter:+word} qui tente également de tester la valeur d'une clé, ce qui n'est pas le sujet du jour .

Utilisation

local -A person=(firstname Anthony lastname Rutledge)

if hasMapKey "firstname" person; then
     # Do something
fi

Lorsqu'on n'effectue pas d'expansion de sous-chaîne, en utilisant la forme décrite (par exemple, ':-'), Bash teste un paramètre qui n'est pas défini ou qui est nul. L'omission des deux points entraîne un test uniquement pour un paramètre qui est non défini. En d'autres termes, si les deux points sont inclus, l'opérateur teste à la fois l'existence du paramètre et le fait que le paramètre est nul. l'existence des deux paramètres et que leur valeur n'est pas nulle ; si le signe deux-points est omis, l'opérateur ne teste que l'existence.

${paramètre:-mot}

If parameter is unset or null, the expansion of word is substituted. Otherwise, the value of parameter is substituted.

${paramètre:=mot}

If parameter is unset or null, the expansion of word is assigned to parameter. The value of parameter is then substituted. Positional

Les paramètres et les paramètres spéciaux ne peuvent pas être affectés de cette manière. ${paramètre:?mot}

If parameter is null or unset, the expansion of word (or a message to that effect if word is not present) is written to the standard

et le shell, s'il n'est pas interactif, quitte. Sinon, la valeur valeur du paramètre est substituée. ${paramètre:+mot}

If parameter is null or unset, nothing is substituted, otherwise the expansion of word is substituted.

https://www.gnu.org/savannah-checkouts/gnu/bash/manual/bash.html#Shell-Parameter-Expansion

Si $needle n'existe pas, sinon il est développé en une chaîne de longueur non nulle, "found". Cela rendra le -n réussissent si le test $needle existe en fait (comme je dis "trouvé"), et échoue dans le cas contraire.

0voto

Jakar Points 6267

Je reçois bad array subscript erreur lorsque la clé que je vérifie n'est pas définie. J'ai donc écrit une fonction qui boucle sur les clés :

#!/usr/bin/env bash
declare -A helpList 

function get_help(){
    target="$1"

    for key in "${!helpList[@]}";do
        if [[ "$key" == "$target" ]];then
            echo "${helpList["$target"]}"
            return;
        fi
    done
}

targetValue="$(get_help command_name)"
if [[ -z "$targetvalue" ]];then
    echo "command_name is not set"
fi

Il fait écho à la valeur lorsqu'elle est trouvée et ne fait rien écho lorsqu'elle n'est pas trouvée. Toutes les autres solutions que j'ai essayées m'ont donné cette erreur.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X