Bash配列に値が含まれているかどうかを確認します

2010年09月10日に質問されました。  ·  閲覧回数 577.3k回  ·  ソース

Paolo Tedesco picture
2010年09月10日

Bashで、配列に特定の値が含まれているかどうかをテストする最も簡単な方法は何ですか?

回答

Keegan picture
2013年03月14日
521

このアプローチには、すべての要素をループする必要がないという利点があります(少なくとも明示的にではありません)。 ただし、 array.cのarray_to_string_internal()は、配列要素をループして文字列に連結するため、提案されているループソリューションよりも効率的ではない可能性がありますが、読みやすくなっています。

if [[ " ${array[@]} " =~ " ${value} " ]]; then
    # whatever you want to do when array contains value
fi

if [[ ! " ${array[@]} " =~ " ${value} " ]]; then
    # whatever you want to do when array doesn't contain value
fi

検索する値がスペースを含む配列要素内の単語の1つである場合、誤検出が発生することに注意してください。 例えば

array=("Jack Brown")
value="Jack"

正規表現は、「ジャック」が配列に含まれていない場合でも、配列に含まれていると見なします。 したがって、このソリューションを引き続き使用する場合は、正規表現のIFSと区切り文字を変更する必要があります。

IFS=$'\t'
array=("Jack Brown\tJack Smith")
unset IFS
value="Jack"

if [[ "\t${array[@]}\t" =~ "\t${value}\t" ]]; then
    echo "true"
else
    echo "false"
fi

これは「false」を出力します。

明らかに、これはテストステートメントとしても使用でき、ワンライナーとして表現できます。

[[ " ${array[@]} " =~ " ${value} " ]] && echo "true" || echo "false"
patrik picture
2011年12月20日
404

以下は、これを実現するための小さな関数です。 検索文字列は最初の引数で、残りは配列要素です。

containsElement () {
  local e match="$1"
  shift
  for e; do [[ "$e" == "$match" ]] && return 0; done
  return 1
}

その関数のテスト実行は次のようになります。

$ array=("something to search for" "a string" "test2000")
$ containsElement "a string" "${array[@]}"
$ echo $?
0
$ containsElement "blaha" "${array[@]}"
$ echo $?
1
ghostdog74 picture
2010年09月11日
58
$ myarray=(one two three)
$ case "${myarray[@]}" in  *"two"*) echo "found" ;; esac
found
Scott picture
2010年09月10日
51
for i in "${array[@]}"
do
    if [ "$i" -eq "$yourValue" ] ; then
        echo "Found"
    fi
done

文字列の場合:

for i in "${array[@]}"
do
    if [ "$i" == "$yourValue" ] ; then
        echo "Found"
    fi
done
JellicleCat picture
2017年11月29日
48

ワンラインソリューション

printf '%s\n' "${myarray[@]}" | grep -P '^mypattern$'

説明

printfステートメントは、配列の各要素を別々の行に出力します。

grepステートメントは、特殊文字^$を使用して、 mypatternとして指定されたパターンを正確に含む行を検索します(これ以上でもそれ以下でもありません)。


使用法

これをif ... thenステートメントに入れるには:

if printf '%s\n' "${myarray[@]}" | grep -q -P '^mypattern$'; then
    # ...
fi

grep式に-qフラグを追加して、一致するものが出力されないようにしました。 一致の存在を「真」として扱うだけです。

LeoRochael picture
2013年01月28日
21

パフォーマンスが必要な場合は、検索するたびに配列全体をループする必要はありません。

この場合、その配列のインデックスを表す連想配列(ハッシュテーブルまたはディクショナリ)を作成できます。 つまり、各配列要素を配列内のインデックスにマップします。

make_index () {
  local index_name=$1
  shift
  local -a value_array=("[email protected]")
  local i
  # -A means associative array, -g means create a global variable:
  declare -g -A ${index_name}
  for i in "${!value_array[@]}"; do
    eval ${index_name}["${value_array[$i]}"]=$i
  done
}

次に、次のように使用できます。

myarray=('a a' 'b b' 'c c')
make_index myarray_index "${myarray[@]}"

そして、次のようにメンバーシップをテストします。

member="b b"
# the "|| echo NOT FOUND" below is needed if you're using "set -e"
test "${myarray_index[$member]}" && echo FOUND || echo NOT FOUND

またはまた:

if [ "${myarray_index[$member]}" ]; then 
  echo FOUND
fi

テストされた値または配列値にスペースがある場合でも、このソリューションは正しいことを行うことに注意してください。

ボーナスとして、配列内の値のインデックスも次のように取得します。

echo "<< ${myarray_index[$member]} >> is the index of $member"
estani picture
2012年07月17日
17

機能のない別の1つのライナー:

(for e in "${array[@]}"; do [[ "$e" == "searched_item" ]] && exit 0; done) && echo "found" || echo "not found"

スペースに関して頭を上げてくれてありがとう@Qwerty!

対応する機能:

find_in_array() {
  local word=$1
  shift
  for e in "[email protected]"; do [[ "$e" == "$word" ]] && return 0; done
  return 1
}

例:

some_words=( these are some words )
find_in_array word "${some_words[@]}" || echo "expected missing! since words != word"
Sean DiSanti picture
2015年01月20日
17

私は通常、次のものを使用します。

inarray=$(echo ${haystack[@]} | grep -o "needle" | wc -w)

ゼロ以外の値は、一致が見つかったことを示します。

Yann picture
2012年05月03日
11
containsElement () { for e in "${@:2}"; do [[ "$e" = "$1" ]] && return 0; done; return 1; }

正しく空の配列を処理します。

hornetbzz picture
2011年02月23日
9

ここに小さな貢献があります:

array=(word "two words" words)  
search_string="two"  
match=$(echo "${array[@]:0}" | grep -o $search_string)  
[[ ! -z $match ]] && echo "found !"  

注:この方法では、「2つの単語」の場合は区別されませんが、質問では必須ではありません。