किसी इंडेक्स या किसी ऐरे में कुंजी की जांच करने का सबसे आसान तरीका?


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. बैश मैनुअल और छोटे नोट में पैरामीटर विस्तार देखें

    यदि बृहदान्त्र को छोड़ दिया जाता है, तो ऑपरेटर केवल अस्तित्व के लिए परीक्षण करता है [ पैरामीटर ]

  2. यह उत्तर वास्तव में इस एसओ प्रश्न के उत्तर से अनुकूलित है: यदि बैश शेल स्क्रिप्ट में स्ट्रिंग को परिभाषित नहीं किया गया है तो कैसे बताएं ?


एक आवरण समारोह:

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 

मैंने इस तरह से हल किया: यदि परीक्षण "$ {myArray ['key_or_index'] + isset}"; फिर प्रतिध्वनि "हाँ"; और प्रतिध्वनि "नहीं"; फाई; यह मुझे सबसे सरल तरीका लगता है और यह अनुक्रमित और साहचर्य सरणियों पर लागू होता है। धन्यवाद
Luca Borrione

1
@doubleDown आप [$ {array [key] + abc}] का उपयोग कैसे करते हैं यदि एक क्लॉज में केवल कुछ करने के लिए अगर [$ {array [key] + abc}] मौजूद नहीं है?
ओलला

1
यह भी काम नहीं करता है जब आप गलती से साहचर्य के रूप में सरणी की गणना करते हैं।
टॉम ज़ातो -

1
@duanev: इसके बिना +abc, [ ${array[key]} ]गलत का मूल्यांकन करेगा यदि तत्व वास्तव में सेट है लेकिन एक खाली मूल्य पर है, इसलिए यह वास्तव में महत्वपूर्ण अस्तित्व के बजाय मूल्य गैर-शून्यता का परीक्षण कर रहा है।
मुशीफिल

@duanev के बिना +abcभी असफल जब array[key]सेट नहीं है और set -uप्रभावी है।
डिंग-यी चेन

35

से आदमी पार्टी , सशर्त भाव:

-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

इससे पता चलेगा कि फू [बार] और फू [बाज] दोनों सेट हैं (भले ही बाद वाला खाली मूल्य पर सेट हो) और फू [क्वक्स] नहीं है।


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 से पहले

दुर्भाग्य से, बैश अंतर betwen खाली और अपरिभाषित चर बनाने के लिए कोई रास्ता नहीं देते हैं ।

लेकिन कुछ तरीके हैं:

$ 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 के रूप में 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 बैश फ़ंक्शन भी बनाएं जो वांछित मान लौटाता है और यदि वांछित मान मौजूद नहीं है तो गलत परिणाम-कोड के साथ बाहर निकलें:

$ 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

डाउनवोट्स के लिए ठीक है: इस उत्तर को बैश के V4.2 से पहले पोस्ट किया गया था ! उत्तर संपादित किया गया!
एफ। होरी

पर काम नहीं करता है bash 4.2.46। पर काम करता है bash 4.4.12
इरफी

@ क्या काम नहीं करता है? या कार्य -vका विकल्प ? testgetIfExist
एफ। हौरी

-vबैश 4.2.46 के साथ मेरे CentOS 1908/07/07 पर सरणियों पर काम नहीं करता। not existउस बैश के तहत सभी मामलों में आपके पहले कोड ब्लॉक से कोड प्रिंट होता है। (इसके [$i]बजाय की कोशिश की [i], कोई फर्क नहीं)
इरफी

5

बैश 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

यह तब विफल रहता है जब कुंजी का मान एक रिक्त स्ट्रिंग है। वर्कअराउंड के रूप में आप +कुछ अंडरहोल्डर की तरह एक खाली मान को बदलने के लिए पैरामीटर विस्तार का उपयोग कर सकते हैं । उदाहरण के लिए declare -A a[x]=;[[ ${a[x]} ]];echo $?प्रिंट 1, लेकिन declare -A a[x]=;[[ ${a[x]+_} ]];echo $?प्रिंट 0
निसटैमा

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

महान कॉम्पैक्ट समाधान जो एक खाली स्ट्रिंग के लिए अपेक्षित है
रेयान डुगन

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

मैंने यह जांचने के लिए एक फ़ंक्शन लिखा है कि क्या एक कुंजी बैश में एक सरणी में मौजूद है:

# 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 बैश के साथ परीक्षण किया गया, संस्करण 4.1.5 (1) -release (i486-pc-linux-gnu)

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.