要素がBashの配列内に存在するかどうかを確認する効率的な方法があるかどうか疑問に思っていましたか?私はPythonでできることと似たようなものを探しています:
arr = ['a','b','c','d']
if 'd' in arr:
do your thing
else:
do something
Bash 4+のbashに連想配列を使用したソリューションを見てきましたが、別のソリューションがあるかどうか疑問に思っています。
些細な解決策は配列を繰り返すことであることは知っていますが、それは望ましくありません。
あなたができる:
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
明らかな注意点は別として、もしあなたの配列が実際に上の配列のようであれば、あなたはできる
if [[ ${arr[*]} =~ d ]]
then
do your thing
else
do something
fi
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
配列要素にスペースが含まれていない場合、別の(おそらく読みやすい)ソリューションは次のようになります。
if echo ${arr[@]} | grep -q -w "d"; then
echo "is in array"
else
echo "is not in array"
fi
array=("Word" "two words") # let's look for "two words"
grep
およびprintf
を使用:(printf '%s\n' "${array[@]}" | grep -x -q "two words") && <run_your_if_found_command_here>
for
を使用:(for e in "${array[@]}"; do [[ "$e" == "two words" ]] && exit 0; done; exit 1) && <run_your_if_found_command_here>
not_found結果の場合は|| <run_your_if_notfound_command_here>
を追加
計算時間の点で、反復するよりも速い別の方法があります。わからない。アイデアは、配列を文字列に変換し、切り捨て、新しい配列のサイズを取得することです。
たとえば、「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`
Bashには組み込みのvaluein
array演算子と=~
演算子または[[ "${array[@]" == *"${item}"* ]]
表記は混乱を招きます。通常、grep
とhere-stringを組み合わせます。
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
FWIW、私が使用したものは次のとおりです。
expr "${arr[*]}" : ".*\<$item\>"
これは、配列項目または検索ターゲットに区切り文字がない場合に機能します。アプリケーションの一般的なケースを解決する必要はありませんでした。