Як перевірити, чи елемент знаходиться у масиві bash?


15

Довідка для простого сценарію

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

Цей скрипт просто не працює, я хочу скрипт, який перевіряє, чи є slack64 у списку (я використовую масив), і просто дати мені, так, чи ні. Я не знаю, як порівняти масив з однією змінною.


5
Де array1працює?
tachomi

Відповіді:


18

Використовуйте інший тип масиву: замість масиву, індексованого цілим числом, використовуйте асоціативний масив, тому ключ (індекс) - це те, що ви будете перевіряти. bash-4.0або пізнішого для цього потрібно.

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

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

У вищесказаному ми насправді не піклуємося про значення, вони повинні бути лише порожніми для цього. Ви можете "інвертувати" індексований масив у новий асоціативний масив, обмінявши ключ і значення:

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"

Це може окупитися, якщо у вас є великі масиви, які часто шукають, оскільки реалізація асоціативних масивів буде ефективнішою, ніж циклі переходу масивів. Він не підходить для кожного випадку використання, оскільки він не може обробляти дублікати (хоча ви можете використовувати значення як лічильник, а не лише 1, як зазначено вище), і він не може обробляти порожній індекс.

Вириваючи складну лінію вище, щоб пояснити "інверсію":

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

14

Прямий спосіб - це повторити цикл:

var=ab
for item in "${array[@]}"; do
    [[ $var == "$item" ]] && echo "$var present in the array"
done

? [[ a == aaa ]]помилково, але відповідність ааа ні?
Жилль Кінот

Тож ОП повинен бути поінформований, що він повинен подбати про те, щоб значення могли містити спеціальні символи, як-от [ ]: клас символів (глобуси)
Жил Квенот

Я не бачу різниці між = і == у баші [[ ]]за те, що ви сказали. Ви протестували?
Жилль Кінот


2

Ця функція працює з асоціативними масивами.

Ми можемо використовувати цю функцію, щоб зробити одне з наступних:

- перевірте, чи має масив певний ключ -----------------> inArray "myKey" $ {! myArray [@]} "

- перевірте, чи містить масив певне значення ---------> 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

2

Ви також можете використовувати grep для цього:

array1 = (prova1 prova2 млявий64)
a = слабкий64
if (printf '% s \ n' "$ {array1 [@]}" | grep -xq $ a); потім
    відлуння "це в"
фі

1
Це передбачає, що елементи масиву не містять символів нового рядка (а також пробіли та символи, як ви забули процитувати $a, і не починати з того, -як ви забули --). Ви можете використовувати %s\0замість %s\nта використовувати grep --null(припускаючи GNU grep або сумісний), оскільки змінні bash ніяк не можуть містити символ NUL. Вам також потрібно буде обробляти випадок порожнього масиву спеціально (оскільки ця команда printf друкує те саме, що і для масиву з одним порожнім елементом). Також зауважте, що тут не потрібно запускати передплату.
Стефан Хазелас

так, це застосовно до простих масивів, як у запитанні.
Петро Кетнер
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.