Как проверить, находится ли элемент в массиве 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 в списке (я использую массив), и просто даю мне, да или нет. Я не знаю, как сравнить массив с одной переменной.


4
Где array1работает?
Тахоми

Ответы:


17

Используйте другой тип массива: вместо целочисленного массива используйте ассоциативный массив, поэтому ключ (индекс) - это то, что вы будете проверять. 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 ]]ложь, но совпадение ааа нет?
Жиль Квено

ТАК ОП должен быть проинформирован о том, что он должен позаботиться о том, чтобы значения могли содержать специальные символы, такие как [ ]: класс символов (globs)
Gilles Quenot

Я не вижу разницы между = и == в bash [[ ]]за то, что вы сказали. Вы проверяли?
Жиль Квено


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 slack64)
а = slack64
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.