81

Bashの配列内に要素が存在するかどうかを確認する効率的な方法があるかどうか疑問に思っていましたか? 次のように、Pythonでできることに似たものを探しています。

arr = ['a','b','c','d']

if 'd' in arr:
    do your thing
else:
    do something

Bash 4+のbashに連想配列を使用したソリューションを見てきましたが、別のソリューションがあるかどうか疑問に思っています。

些細な解決策は配列を反復することであることはわかっていますが、それは望ましくありません。

4

8 に答える 8

112

あなたができること:

if [[ " ${arr[*]} " == *" d "* ]]; then
    echo "arr contains d"
fi

これにより、たとえば「a b」を検索した場合に誤検知が発生します。そのサブ文字列は結合された文字列に含まれますが、配列要素としては含まれません。このジレンマは、選択した区切り文字で発生します。

最も安全な方法は、要素が見つかるまで配列をループすることです。

array_contains () {
    local seeking=$1; shift
    local in=1
    for element; do
        if [[ $element == "$seeking" ]]; then
            in=0
            break
        fi
    done
    return $in
}

arr=(a b c "d e" f g)
array_contains "a b" "${arr[@]}" && echo yes || echo no    # no
array_contains "d e" "${arr[@]}" && echo yes || echo no    # yes

これは、すべての要素ではなく、配列名を渡すだけの「よりクリーンな」バージョンです。

array_contains2 () { 
    local array="$1[@]"
    local seeking=$2
    local in=1
    for element in "${!array}"; do
        if [[ $element == "$seeking" ]]; then
            in=0
            break
        fi
    done
    return $in
}

array_contains2 arr "a b"  && echo yes || echo no    # no
array_contains2 arr "d e"  && echo yes || echo no    # yes

連想配列の場合、配列に特定のキーが含まれているかどうかをテストするための非常に整然とした方法があります。-v演算子

$ declare -A arr=( [foo]=bar [baz]=qux )
$ [[ -v arr[foo] ]] && echo yes || echo no
yes
$ [[ -v arr[bar] ]] && echo yes || echo no
no

マニュアルの6.4Bash条件式を参照してください。

于 2013-01-16T20:37:30.827 に答える
36

明らかな警告はさておき、配列が実際に上記のようなものである場合、次のことができます

if [[ ${arr[*]} =~ d ]]
then
  do your thing
else
  do something
fi
于 2013-01-16T19:58:54.567 に答える
24

1) 配列の初期化arrと要素の追加

2) 検索する変数を設定するSEARCH_STRING

3)配列に要素が含まれているかどうかを確認します

arr=()
arr+=('a')
arr+=('b')
arr+=('c')

SEARCH_STRING='b'

if [[ " ${arr[*]} " == *"$SEARCH_STRING"* ]];
then
    echo "YES, your arr contains $SEARCH_STRING"
else
    echo "NO, your arr does not contain $SEARCH_STRING"
fi
于 2016-12-30T12:04:29.373 に答える
19

配列要素にスペースが含まれていない場合、別の (おそらくより読みやすい) 解決策は次のようになります。

if echo ${arr[@]} | grep -q -w "d"; then 
    echo "is in array"
else 
    echo "is not in array"
fi
于 2015-12-03T12:45:52.427 に答える
3

bash には組み込みの in 配列演算子がなく、=~演算子または[[ "${array[@]" == *"${item}"* ]]表記法が私を混乱させ続けるため、通常はgrepヒア文字列と組み合わせます。

colors=('black' 'blue' 'light green')
if grep -q 'black' <<< "${colors[@]}"
then
    echo 'match'
fi

ただし、これは、検索するアイテムが完全に含まれているが、別のアイテムと等しくない場合に発生する他の多くの回答と同じ誤検知の問題があることに注意してください。

if grep -q 'green' <<< "${colors[@]}"
then
    echo 'should not match, but does'
fi

それがユース ケースの問題である場合は、おそらく配列のループを回避できないでしょう。

for color in "${colors[@]}"
do
    if [ "${color}" = 'green' ]
    then
        echo "should not match and won't"
        break
    fi
done

for color in "${colors[@]}"
do
    if [ "${color}" = 'light green' ]
    then
        echo 'match'
        break
    fi
done
于 2019-07-04T05:50:43.843 に答える
2

計算時間の点で、反復よりも高速な別の方法を次に示します。わからない。アイデアは、配列を文字列に変換し、切り捨てて、新しい配列のサイズを取得することです。

たとえば、「d」のインデックスを見つけるには:

arr=(a b c d)    
temp=`echo ${arr[@]}`
temp=( ${temp%%d*} )
index=${#temp[@]}

これを次のような関数に変換できます。

get-index() {

    Item=$1
    Array="$2[@]"

    ArgArray=( ${!Array} )
    NewArray=( ${!Array%%${Item}*} )

    Index=${#NewArray[@]}

    [[ ${#ArgArray[@]} == ${#NewArray[@]} ]] && echo -1 || echo $Index

}

次に、次のように呼び出すことができます。

get-index d arr

そしてそれは 3 をエコー バックします。これは次のように割り当て可能です。

index=`get-index d arr`
于 2015-02-26T02:52:47.220 に答える
0

FWIW、これが私が使用したものです:

expr "${arr[*]}" : ".*\<$item\>"

これは、配列項目または検索対象に区切り文字がない場合に機能します。アプリケーションの一般的なケースを解決する必要はありませんでした。

于 2015-07-13T19:13:11.987 に答える