Làm cách nào để kiểm tra nếu một mục nằm trong mảng bash?


15

Trợ giúp cho một kịch bản đơn giản

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

Kịch bản này đơn giản là không hoạt động, tôi muốn một kịch bản kiểm tra xem slack64 có trong danh sách không (tôi sử dụng một mảng) và chỉ cần đưa cho tôi, có hay không. Tôi không biết làm thế nào để so sánh một mảng với một biến duy nhất.


4
Nơi nào array1làm việc?
tachomi

Câu trả lời:


17

Sử dụng một loại mảng khác: thay vì mảng được lập chỉ mục số nguyên, sử dụng mảng kết hợp, vì vậy khóa (chỉ mục) là thứ bạn sẽ kiểm tra. bash-4.0hoặc sau này là cần thiết cho việc này.

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

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

Ở trên chúng tôi không thực sự quan tâm đến các giá trị, chúng chỉ cần không trống cho việc này. Bạn có thể "đảo ngược" một mảng được lập chỉ mục thành một mảng kết hợp mới bằng cách trao đổi khóa và giá trị:

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"

Điều này có thể trả hết nếu bạn có các mảng lớn thường được tìm kiếm, vì việc thực hiện các mảng kết hợp sẽ hoạt động tốt hơn các vòng lặp đi qua mảng. Mặc dù vậy, nó sẽ không phù hợp với mọi trường hợp sử dụng, vì nó không thể xử lý các bản sao (mặc dù bạn có thể sử dụng giá trị làm bộ đếm, thay vì chỉ 1 như trên) và nó không thể xử lý một chỉ mục trống.

Phá vỡ dòng phức tạp ở trên, để giải thích "nghịch đả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

14

Cách đơn giản là lặp lại với một vòng lặp:

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

? [[ a == aaa ]]là sai nhưng một trận đấu aaa không?
Gilles Quenot

Vì vậy, OP nên được thông báo rằng anh ta phải cẩn thận nếu các giá trị có thể chứa các ký tự đặc biệt, như [ ]: lớp nhân vật (quả cầu)
Gilles Quenot

Tôi thấy không có sự khác biệt giữa = và == trong bash [[ ]]cho những gì bạn nói. Bạn đã thử chưa?
Gilles Quenot

2

Với zsh:

array1=(
  prova1
  prova2
  slack64
)

a=slack64

if ((array1[(Ie)$a])); then
  printf '%s\n' "$a in array1"
fi

2

Hàm này hoạt động với các mảng kết hợp.

Chúng ta có thể sử dụng chức năng này để thực hiện một trong những điều sau đây:

- kiểm tra xem mảng có một khóa nhất định -----------------> inArray "myKey" $ {! myArray [@]} "

- kiểm tra xem mảng có chứa một giá trị nhất định ---------> 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

Bạn cũng có thể sử dụng grep cho điều đó:

mảng1 = (prova1 prova2 slack64)
a = slack64
if (printf '% s \ n' "$ {mảng1 [@]}" | grep -xq $ a); sau đó
    tiếng vang "nó ở"
fi

1
Giả sử các thành phần mảng không chứa các ký tự dòng mới (và khoảng trắng và ký tự đại diện khi bạn quên trích dẫn $avà không bắt đầu -khi bạn quên --). Bạn có thể sử dụng %s\0thay vì %s\nvà sử dụng grep --null(giả sử GNU grep hoặc tương thích) vì các biến bash không thể chứa ký tự NUL. Bạn cũng cần xử lý trường hợp của một mảng trống đặc biệt (vì lệnh printf sẽ in tương tự như đối với một mảng có một phần tử trống). Cũng lưu ý rằng bạn không cần phải bắt đầu một subshell ở đây.
Stéphane Chazelas

vâng, nó được áp dụng trên các mảng đơn giản như trong câu hỏi.
Petr Ketner
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.