Jak sprawdzić, czy element znajduje się w tablicy bash?

15

Pomoc dla prostego skryptu

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

Ten skrypt po prostu nie działa, chcę skryptu, który sprawdza, czy slack64 jest obecny na liście (używam tablicy), i po prostu daje mi, tak, jest obecny lub nie. Nie wiem, jak porównać tablicę z jedną zmienną.

Elbarna
źródło
5
Gdzie array1działa?
tachomi

Odpowiedzi:

18

Użyj innego rodzaju tablicy: zamiast tablicy indeksowanej liczbami całkowitymi użyj tablicy asocjacyjnej, więc klucz (indeks) jest tym, czego będziesz szukał. bash-4.0lub później jest to wymagane.

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

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

W powyższym przypadku tak naprawdę nie dbamy o wartości, muszą one być tylko puste. Możesz „odwrócić” indeksowaną tablicę na nową tablicę asocjacyjną, wymieniając klucz i wartość:

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"

Może się to opłacić, jeśli masz często wyszukiwane duże tablice, ponieważ implementacja tablic asocjacyjnych będzie działać lepiej niż pętle przeszukiwania tablic. Nie będzie pasował do każdego przypadku użycia, ponieważ nie może obsługiwać duplikatów (chociaż można użyć wartości jako licznika, zamiast tylko 1 jak powyżej) i nie może obsłużyć pustego indeksu.

Przełamując powyższą złożoną linię, aby wyjaśnić „inwersję”:

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
pan. spuratic
źródło
14

Najprostszym sposobem jest iteracja w pętli:

var=ab
for item in "${array[@]}"; do
    [[ $var == "$item" ]] && echo "$var present in the array"
done
Gilles Quenot
źródło
? [[ a == aaa ]]jest fałszywe, ale dopasowanie aaa nie?
Gilles Quenot
W związku z tym PO należy poinformować, że musi uważać, czy wartości mogą zawierać znaki specjalne, takie jak [ ]: klasa postaci (globs)
Gilles Quenot
Nie widzę żadnej różnicy między = i == w bash [[ ]]dla tego, co powiedziałeś. Testowałeś?
Gilles Quenot,
2

Z zsh:

array1=(
  prova1
  prova2
  slack64
)

a=slack64

if ((array1[(Ie)$a])); then
  printf '%s\n' "$a in array1"
fi
Stéphane Chazelas
źródło
2

Ta funkcja działa z tablicami asocjacyjnymi.

Możemy użyć tej funkcji, aby wykonać jedną z następujących czynności:

- sprawdź, czy tablica ma określony klucz -----------------> inArray „myKey” $ {! myArray [@]} ”

- sprawdź, czy tablica zawiera pewną wartość ---------> 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
molwa
źródło
2

Możesz również użyć do tego grep:

array1 = (prova1 prova2 slack64)
a = slack64
if (printf '% s \ n' "$ {array1 [@]}" | grep -xq $ a); następnie
    echo „jest w”
fi
Petr Ketner
źródło
1
Zakłada się, że elementy tablicy nie zawierają znaków nowej linii (oraz spacji i symboli wieloznacznych, o których zapomniałeś cytować $a, i nie zaczynaj -od zapomnienia --). Możesz użyć %s\0zamiast %s\ni użyć grep --null(zakładając, że GNU grep lub zgodny), ponieważ zmienne bash i tak nie mogą zawierać znaku NUL. Trzeba by również specjalnie traktować przypadek pustej tablicy (ponieważ to polecenie printf wypisuje to samo, co w przypadku tablicy z jednym pustym elementem). Pamiętaj też, że nie musisz tutaj uruchamiać podpowłoki.
Stéphane Chazelas
tak, ma zastosowanie do prostych tablic takich jak ten w pytaniu.
Petr Ketner,