Comment puis-je tester si un élément est dans un tableau bash?

15

Aide pour un script simple

#!/bin/bash

array1=(
prova1
prova2
slack64
)

a="slack64"
b="ab"

if [ $a = $b ]
then
      echo "$a = $b : a is equal to b"
else
      echo "$a = $b: a is not equal to b"
fi

Ce script ne fonctionne tout simplement pas, je veux un script qui vérifie si slack64 est présent dans une liste (j'utilise un tableau), et me donne simplement, oui est présent ou non. Je ne sais pas comment comparer un tableau avec une seule variable.

elbarna
la source
4
Où est le array1travail?
tachomi

Réponses:

17

Utilisez un autre type de tableau: plutôt qu'un tableau indexé sur des nombres entiers, utilisez un tableau associatif, donc la clé (index) est celle que vous allez rechercher. bash-4.0ou plus tard est nécessaire pour cela.

declare -A array1=( 
 [prova1]=1  [prova2]=1  [slack64]=1
)

a=slack64
[[ -n "${array1[$a]}" ]] && printf '%s is in array\n' "$a"

Dans ce qui précède, nous ne nous soucions pas vraiment des valeurs, elles doivent seulement être non vides pour cela. Vous pouvez "inverser" un tableau indexé dans un nouveau tableau associatif en échangeant la clé et la valeur:

declare -a array1=( 
 prova1 prova2 slack64
)
declare -A map    # required: declare explicit associative array
for key in "${!array1[@]}"; do map[${array1[$key]}]="$key"; done  # see below

a=slack64
[[ -n "${map[$a]}" ]] && printf '%s is in array\n' "$a"

Cela peut être payant si vous avez de grands tableaux qui sont fréquemment recherchés, car la mise en œuvre de tableaux associatifs fonctionnera mieux que les boucles traversant les tableaux. Cependant, il ne conviendra pas à tous les cas d'utilisation, car il ne peut pas gérer les doublons (bien que vous puissiez utiliser la valeur comme compteur, au lieu de 1 comme ci-dessus), et il ne peut pas gérer un index vide.

Éclatant la ligne complexe ci-dessus, pour expliquer "l'inversion":

for key in "${!a[@]}"     # expand the array indexes to a list of words
do 
  map[${a[$key]}]="$key"  # exchange the value ${a[$key]} with the index $key
done
Mr Spuratic
la source
14

La manière la plus simple est d'itérer avec une boucle:

var=ab
for item in "${array[@]}"; do
    [[ $var == "$item" ]] && echo "$var present in the array"
done
Gilles Quenot
la source
? [[ a == aaa ]]est faux mais un match aaa non?
Gilles Quenot
DONC le PO doit être informé qu'il doit faire attention si les valeurs peuvent contenir des caractères spéciaux, comme [ ]: classe de caractères (globes)
Gilles Quenot
Je ne vois aucune différence entre = et == en bash [[ ]]pour ce que vous avez dit. Avez-vous testé?
Gilles Quenot
2

Avec zsh:

array1=(
  prova1
  prova2
  slack64
)

a=slack64

if ((array1[(Ie)$a])); then
  printf '%s\n' "$a in array1"
fi
Stéphane Chazelas
la source
2

Cette fonction fonctionne avec des tableaux associatifs.

Nous pouvons utiliser cette fonction pour effectuer l'une des opérations suivantes:

- vérifier si le tableau a une certaine clé -----------------> inArray "myKey" $ {! myArray [@]} "

- vérifier si le tableau contient une certaine valeur ---------> inArray "myValue" "$ {myArray [@]}"

function inArray # ( keyOrValue, arrayKeysOrValues ) 
{
  local e
  for e in "${@:2}"; do 
    [[ "$e" == "$1" ]] && return 0; 
  done
  return 1
}

declare -A arr
arr[doo]=55

inArray "doo" "${!arr[@]}"
echo $?     # 0 
inArray "bla" "${!arr[@]}"
echo $?     # 1 
inArray "55" "${arr[@]}"
echo $?     # 0
lingue
la source
2

Vous pouvez également utiliser grep pour cela:

array1 = (prova1 prova2 slack64)
a = slack64
if (printf '% s \ n' "$ {array1 [@]}" | grep -xq $ a); ensuite
    l'écho "c'est dedans"
Fi
Petr Ketner
la source
1
Cela suppose les éléments du tableau ne contiennent pas de caractères (et blancs de saut de ligne et que les jokers vous avez oublié de citer $a, et ne commencent pas -que vous avez oublié le --). Vous pouvez utiliser %s\0au lieu de %s\net utiliser grep --null(en supposant GNU grep ou compatible) car les variables bash ne peuvent pas contenir le caractère NUL de toute façon. Vous devez également gérer le cas d'un tableau vide spécialement (car cette commande printf imprimerait la même chose que pour un tableau avec un élément vide). Notez également que vous n'avez pas besoin de démarrer un sous-shell ici.
Stéphane Chazelas
oui, il est applicable sur les tableaux simples comme celui de la question.
Petr Ketner