配列内のインデックスまたはキーをチェックする最も簡単な方法は?


89

使用:

set -o nounset
  1. 次のようなインデックス付き配列を持つ:

    myArray=( "red" "black" "blue" )
    

    要素1が設定されているかどうかを確認する最短の方法は何ですか?
    私は時々以下を使用します:

    test "${#myArray[@]}" -gt "1" && echo "1 exists" || echo "1 doesn't exist"
    

    好きなものがあるか知りたいのですが。

  2. 非連続インデックスを処理する方法は?

    myArray=()
    myArray[12]="red"
    myArray[51]="black"
    myArray[129]="blue"
    

    51たとえば、すでに設定されているものをすばやく確認するにはどうすればよいですか?

  3. 連想配列を処理する方法は?

    declare -A myArray
    myArray["key1"]="red"
    myArray["key2"]="black"
    myArray["key3"]="blue"
    

    key2たとえば、すでに使用されているものをすばやく確認するにはどうすればよいですか?

回答:


130

要素が設定されているかどうかを確認するには(インデックス付き配列と連想配列の両方に適用されます)

[ ${array[key]+abc} ] && echo "exists"

基本的には何${array[key]+abc}ですか

  • array[key]が設定されている場合は、abc
  • array[key]が設定されていない場合、何も返しません


参照:

  1. Bashマニュアルのパラメータ拡張と小さなメモを参照してください

    コロンが省略されている場合、演算子は[パラメータの存在]のみをテストします

  2. この回答は、実際にはこのSOの質問に対する回答を基にしています。bashシェルスクリプトで文字列が定義されていないかどうかを確認するにはどうすればよいですか?


ラッパー関数:

exists(){
  if [ "$2" != in ]; then
    echo "Incorrect usage."
    echo "Correct usage: exists {key} in {array}"
    return
  fi   
  eval '[ ${'$3'[$1]+muahaha} ]'  
}

例えば

if ! exists key in array; then echo "No such array element"; fi 

私はこのように解決しました:if test "$ {myArray ['key_or_index'] + isset}"; 次に、「はい」をエコーし​​ます。それ以外の場合は「いいえ」をエコーし​​ます。fi; それは私には最も簡単な方法のように思われ、インデックス付きの連想配列に適用されます。ありがとう
Luca Borrione 2012年

1
@doubleDown [$ {array [key] + abc}]が存在しない場合にのみ何かを行うために、if句で[$ {array [key] + abc}]をどのように使用しますか?
olala 2014

1
また、列挙された配列を誤って連想配列としてクエリした場合も機能しません。
トマシュザト-モニカを復活させる2015年

1
@duanev:がない+abc[ ${array[key]} ]、要素が実際に設定されているが空の値に設定されている場合はfalseと評価されるため、実際には、キーの存在ではなく、値が空でないことをテストしています。
musiphil

@duanev設定されていない+abc場合も失敗せず、有効です。array[key]set -u
Ding-Yi Chen

35

man bashから、条件式:

-v varname
              True if the shell variable varname is set (has been assigned a value).

例:

declare -A foo
foo[bar]="this is bar"
foo[baz]=""
if [[ -v "foo[bar]" ]] ; then
  echo "foo[bar] is set"
fi
if [[ -v "foo[baz]" ]] ; then
  echo "foo[baz] is set"
fi
if [[ -v "foo[quux]" ]] ; then
  echo "foo[quux] is set"
fi

これは、foo [bar]とfoo [baz]の両方が設定されており(後者が空の値に設定されている場合でも)、foo [quux]が設定されていないことを示しています。


1
一目見ただけで見逃しました。一般的な配列拡張構文が使用されていないことに注意してください。
ネイサンチャペル

を使用すると、辞書に存在しない場合set -u、なぜ[[ -v "${foo[bar]}" ]]バインドされていない変数エラーが生成されるのbarですか?${};なしで正常に動作します。私はデフォルトですべてにそれを使用することに慣れています。
bgfvdu3w

"${foo[bar]}"最初に配列変数を評価するため、[[ -vコマンドはその値の名前を持つ変数をテストします
andysh

10

新しい答え

のバージョン4.2から (およびそれ以降)、-v組み込みtestコマンドに新しいオプションがあります 。

array=([12]="red" [51]="black" [129]="blue")

for i in 10 12 30 {50..52} {128..131};do
    if [ -v array[i] ];then
        echo "Variable 'array[$i]' is defined"
    else
        echo "Variable 'array[$i]' not exist"
    fi
done
Variable 'array[10]' not exist
Variable 'array[12]' is defined
Variable 'array[30]' not exist
Variable 'array[50]' not exist
Variable 'array[51]' is defined
Variable 'array[52]' not exist
Variable 'array[128]' not exist
Variable 'array[129]' is defined
Variable 'array[130]' not exist
Variable 'array[131]' not exist

これは、連想配列でも同じように機能します。

declare -A aArray=([foo]="bar" [bar]="baz" [baz]=$'Hello world\041')

for i in alpha bar baz dummy foo test;do
    if [ -v aArray[$i] ];then
        echo "Variable 'aArray[$i]' is defined"
    else
        echo "Variable 'aArray[$i]' not exist"
    fi
done
Variable 'aArray[alpha]' not exist
Variable 'aArray[bar]' is defined
Variable 'aArray[baz]' is defined
Variable 'aArray[dummy]' not exist
Variable 'aArray[foo]' is defined
Variable 'aArray[test]' not exist

少し違いがあります
。通常の配列では、角かっこ([i])間の変数は整数であるため、ドル記号($)は必要ありませんが、連想配列の場合、キーは単語で$あるため、必要です([$i])!

の古い答え V4.2より前

残念ながら、bashは空の変数と未定義の変数を区別する方法を提供しません。

しかし、いくつかの方法があります。

$ array=()
$ array[12]="red"
$ array[51]="black"
$ array[129]="blue"

$ echo ${array[@]}
red black blue

$ echo ${!array[@]}
12 51 129

$ echo "${#array[@]}"
3

$ printf "%s\n" ${!array[@]}|grep -q ^51$ && echo 51 exist
51 exist

$ printf "%s\n" ${!array[@]}|grep -q ^52$ && echo 52 exist

(答えない)

連想配列の場合、同じものを使用できます。

$ unset array
$ declare -A array
$ array["key1"]="red"
$ array["key2"]="black"
$ array["key3"]="blue"
$ echo ${array[@]}
blue black red

$ echo ${!array[@]}
key3 key2 key1

$ echo ${#array[@]}
3

$ set | grep ^array=
array=([key3]="blue" [key2]="black" [key1]="red" )

$ printf "%s\n" ${!array[@]}|grep -q ^key2$ && echo key2 exist || echo key2 not exist
key2 exist

$ printf "%s\n" ${!array[@]}|grep -q ^key5$ && echo key5 exist || echo key5 not exist
key5 not exist

外部ツールを必要とせずにジョブを実行でき(純粋なbashとしてprintf | grepはありません、新しいbash関数としてcheckIfExist()をビルドします。

$ checkIfExist() {
    eval 'local keys=${!'$1'[@]}';
    eval "case '$2' in
        ${keys// /|}) return 0 ;;
        * ) return 1 ;;
      esac";
}

$ checkIfExist array key2 && echo exist || echo don\'t
exist

$ checkIfExist array key5 && echo exist || echo don\'t
don't

または、新しいgetIfExist bash関数を作成して、目的の値を返し、目的の値が存在しない場合はfalseの結果コードで終了します。

$ getIfExist() {
    eval 'local keys=${!'$1'[@]}';
    eval "case '$2' in
        ${keys// /|}) echo \${$1[$2]};return 0 ;;
        * ) return 1 ;;
      esac";
}

$ getIfExist array key1
red
$ echo $?
0

$ # now with an empty defined value
$ array["key4"]=""
$ getIfExist array key4

$ echo $?
0
$ getIfExist array key5
$ echo $?
1

反対票でOK:この回答はbashのV4.2より前に投稿されました!回答編集!
F. HAURI

では動作しませんbash 4.2.46。で動作しbash 4.4.12ます。
Irfy

@Irfy何が機能しないのですか?-vオプションtestまたはgetIfExist機能?
F. HAURI

-vbashの4.2.46と私のCentOSの1908年7月7日にアレイ上では動作しません。最初のコードブロックのコードはnot exist、すべての場合にそのbashの下に出力されます。([$i]代わりに試しましたが[i]、違いはありません)
Irfy

5

bash 4.3.39(1)でテスト済み-リリース

declare -A fmap
fmap['foo']="boo"

key='foo'
# should echo foo is set to 'boo'
if [[ -z "${fmap[${key}]}" ]]; then echo "$key is unset in fmap"; else echo "${key} is set to '${fmap[${key}]}'"; fi
key='blah'
# should echo blah is unset in fmap
if [[ -z "${fmap[${key}]}" ]]; then echo "$key is unset in fmap"; else echo "${key} is set to '${fmap[${key}]}'"; fi

キーの値が空の文字列の場合、これは失敗します。回避策として、+パラメーター展開を使用して、空の値をアンダースコアなどのプレースホルダーに置き換えることができます。例のためのdeclare -A a[x]=;[[ ${a[x]} ]];echo $?プリント1が、declare -A a[x]=;[[ ${a[x]+_} ]];echo $?プリント0
nisetama 2015

3

何についての-zテストと:-オペレータ?

たとえば、次のスクリプトは次のとおりです。

#!/usr/bin/env bash

set -e
set -u

declare -A sample

sample["ABC"]=2
sample["DEF"]=3

if [[ ! -z "${sample['ABC']:-}" ]]; then
  echo "ABC is set"
fi

if [[ ! -z "${sample['DEF']:-}" ]]; then
  echo "DEF is set"
fi

if [[ ! -z "${sample['GHI']:-}" ]]; then
  echo "GHI is set"
fi

プリント:

ABC is set
DEF is set

空の文字列に対して期待どおりに応答する優れたコンパクトなソリューション
Ryan Dugan

1

これは私がスクリプトで見つけた最も簡単な方法です。

<search>は検索する文字列でありASSOC_ARRAY、連想配列を保持する変数の名前です。

達成したいことに依存します:

キーが存在します

if grep -qe "<search>" <(echo "${!ASSOC_ARRAY[@]}"); then echo key is present; fi

キーが存在しません

if ! grep -qe "<search>" <(echo "${!ASSOC_ARRAY[@]}"); then echo key not present; fi

値が存在します

if grep -qe "<search>" <(echo "${ASSOC_ARRAY[@]}"); then echo value is present; fi

値が存在しません

if ! grep -qe "<search>" <(echo "${ASSOC_ARRAY[@]}"); then echo value not present; fi

1

Bashの配列にキーが存在するかどうかをチェックする関数を作成しました。

# Check if array key exists
# Usage: array_key_exists $array_name $key
# Returns: 0 = key exists, 1 = key does NOT exist
function array_key_exists() {
    local _array_name="$1"
    local _key="$2"
    local _cmd='echo ${!'$_array_name'[@]}'
    local _array_keys=($(eval $_cmd))
    local _key_exists=$(echo " ${_array_keys[@]} " | grep " $_key " &>/dev/null; echo $?)
    [[ "$_key_exists" = "0" ]] && return 0 || return 1
}

declare -A my_array
my_array['foo']="bar"

if [[ "$(array_key_exists 'my_array' 'foo'; echo $?)" = "0" ]]; then
    echo "OK"
else
    echo "ERROR"
fi

GNU bash、バージョン4.1.5(1)-リリース(i486-pc-linux-gnu)でテスト済み

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.