항목이 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작업 은 어디 입니까?
tachomi

답변:


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 ]]거짓이지만 일치 aaa no?
Gilles Quenot

따라서 OP는 값에 다음과 같은 특수 문자가 포함될 수있는 경우주의를 기울여야한다는 사실을 알아야합니다 [ ]. 문자 클래스 (글로브)
Gilles Quenot

나는 [[ ]]당신이 말한 것에 대해 bash에서 =와 ==의 차이가 보이지 않습니다 . 테스트 했습니까?
Gilles Quenot

2

zsh:

array1=(
  prova1
  prova2
  slack64
)

a=slack64

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

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)
a = 슬랙 64
if (printf '% s \ n' "$ {array1 [@]}"| grep -xq $ a); 그때
    에코 "있다"
fi

1
즉, 배열 요소는 (당신이 인용하는 것을 잊었다로하고 공백 와일드 카드 개행 문자를 포함하지 않는 가정 $a하고 시작하지 않는 -당신은 잊었으로 --). 당신이 사용할 수있는 %s\0대신에 %s\n사용 grep --null어쨌든 NUL 문자를 포함 할 수 없습니다 bash는 변수로 (GNU 그렙 또는 호환 가정). 빈 배열의 경우를 특별히 처리해야합니다 (printf 명령은 하나의 빈 요소가있는 배열과 동일한 내용을 인쇄하므로). 또한 여기에서 서브 쉘을 시작할 필요가 없습니다.
Stéphane Chazelas

예, 문제의 배열과 같은 간단한 배열에 적용 할 수 있습니다.
Petr Ketner
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.