web-dev-qa-db-ja.com

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

を使用して:

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」がすでに使用されていることをすばやく確認するにはどうすればよいですか?

ありがとう

[〜#〜]編集済み[〜#〜]
最も簡単な方法は私には思えます:

if test "${myArray['key_or_index']+isset}"
    then
        echo "yes"
    else
        echo "no"
fi;

これは、インデックス付き配列と連想配列の両方で機能します。 set -o nounsetでエラーは表示されません。
ヘッドアップのdoubleDownに感謝します。

72
Luca Borrione

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

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

基本的に何${array[key]+abc}

  • if array[key]が設定され、abcを返します
  • if array[key]は設定されていません。何も返しません

  1. Bashマニュアルの「 Parameter Expansion 」と小さなメモを参照してください

    コロンが省略された場合、演算子は、[parameter]の存在のみをテストします

  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 
107
doubleDown

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]は設定されていません。

21
Vineet

残念ながら、bashはemptyundefined変数を区別する方法を提供しません。

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

$ 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

あなたは外部ツールを必要とせずに仕事をすることができます(printf | grep aspure bash)、そしてなぜ、ビルドしないcheckIfExist()新しいbash関数として:

$ 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

または、必要な値を返し、必要な値が存在しない場合は偽の結果コードで終了する新しいgetIfExistbash関数を作成することもできます。

$ 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
6
F. Hauri

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

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
5
gdoubleod

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)-release(i486-pc-linux-gnu)でテスト済み

1
Lucas Stad

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

<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
sjas

-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
0
GuyPaddock