Como testar se um item está em uma matriz bash?

15

Ajuda para um script simples

#!/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

Este script simplesmente não funciona, eu quero um script que verifique se slack64 está presente em uma lista (eu uso uma matriz) e simplesmente me dê, yes está presente ou não. Não sei como comparar uma matriz com uma única variável.

elbarna
fonte
4
Onde é que o array1trabalho?
tachomi

Respostas:

17

Use um tipo diferente de matriz: em vez de uma matriz indexada por número inteiro, use uma matriz associativa; portanto, a chave (índice) é o que você procurará. bash-4.0ou posterior é necessário para isso.

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

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

No exposto acima, nós realmente não nos importamos com os valores, eles precisam estar apenas vazios para isso. Você pode "inverter" uma matriz indexada em uma nova matriz associativa trocando a chave e o valor:

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"

Isso pode valer a pena se você tiver grandes matrizes que são frequentemente pesquisadas, pois a implementação de matrizes associativas terá um desempenho melhor do que os loops que atravessam a matriz. Porém, ele não serve para todos os casos de uso, pois não pode manipular duplicatas (embora você possa usar o valor como um contador, em vez de apenas 1 como acima), e não pode manipular um índice vazio.

Rompendo a linha complexa acima, para explicar a "inversão":

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
fonte
14

A maneira direta é iterar com um loop:

var=ab
for item in "${array[@]}"; do
    [[ $var == "$item" ]] && echo "$var present in the array"
done
Gilles Quenot
fonte
? [[ a == aaa ]]é falso, mas uma correspondência aaa não?
Gilles Quenot
Assim, o OP deve ser informado que ele tem que tomar cuidado se os valores podem conter caracteres especiais, como [ ]: classe de personagem (bolhas)
Gilles Quenot
Não vejo diferença entre = e == no bash [[ ]]para o que você disse. Você já testou?
Gilles Quenot
2

Com zsh:

array1=(
  prova1
  prova2
  slack64
)

a=slack64

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

Esta função trabalha com matrizes associativas.

Podemos usar esta função para executar um dos seguintes procedimentos:

- verifique se a matriz possui uma determinada chave -----------------> inArray "myKey" $ {! myArray [@]} "

- verifique se a matriz contém um determinado valor ---------> 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
ling
fonte
2

Você também pode usar o grep para isso:

array1 = (prova1 prova2 slack64)
a = slack64
if (printf '% s \ n' "$ {array1 [@]}" | grep -xq $ a); então
    eco "está dentro"
fi
Petr Ketner
fonte
1
Isso pressupõe que os elementos da matriz não contenham caracteres de nova linha (e espaços em branco e curingas como você esqueceu de citar $ae não comece com -como você esqueceu a --). Você pode usar em %s\0vez de %s\ne usar grep --null(assumindo GNU grep ou compatível), pois as variáveis ​​bash não podem conter o caractere NUL de qualquer maneira. Você também precisaria lidar especialmente com o caso de uma matriz vazia (pois esse comando printf imprimiria a mesma coisa que uma matriz com um elemento vazio). Observe também que você não precisa iniciar um subshell aqui.
Stéphane Chazelas
sim, é aplicável em matrizes simples como a da pergunta.
precisa