शैल लिपियों में सहयोगी सारणी


11

मैंने एक शेल स्क्रिप्ट में साहचर्य सरणियों को लागू करने के लिए एक चाल देखी। उदाहरण के लिए कुंजी = सेब के print array["apples"]रूप में लिपिबद्ध किया जा सकता है echo \$array$key

हालाँकि, सरणी पर पुनरावृति करने के लिए कुंजियों को उत्पन्न करने का कोई उल्लेख नहीं किया गया था। एक ही रास्ता मैं सोच सकता था कि रिक्त स्थान द्वारा सीमांकित एक चर में कुंजियों को संग्रहीत करना है ताकि मैं सरणी पर पुनरावृति करने के लिए एक लूप का उपयोग कर सकूं।

तो, क्या बाद में उपयोग के लिए कुंजी स्टोर करने का कोई और तरीका है?


5
यदि आप एक शेल स्क्रिप्ट में साहचर्य सरणियों का उपयोग करने की कोशिश कर रहे हैं तो यह संभव हो सकता है कि आपकी परियोजना शेल स्क्रिप्ट के लिए बहुत जटिल है :)
मार्टिन वॉन विटिच

@MartinvonWittich क्यों? मेरे पास एक शेल स्क्रिप्ट है जो 3 संभावित DB स्कीमाओं में से एक पर SQL स्क्रिप्ट निष्पादित करता है। आवश्यक स्कीमा को एक संक्षिप्त नाम के साथ फ़ाइल नाम में शामिल किया गया है। मुझे इस संक्षिप्त नाम और वास्तविक स्कीमा नाम के बीच मानचित्रण की आवश्यकता है। एक सहयोगी सरणी से बेहतर तरीका क्या है, वास्तविक स्कीमा नामों (संक्षिप्त नाम नहीं) पर विचार करना पर्यावरण के बीच भिन्न हो सकता है, इसलिए एक सरणी चर (जिसका मान बस एक बार सेट किया जा सकता है) एकदम सही है
स्लैव

2
@ मैं साहचर्य सरणियों के खिलाफ बहस नहीं कर रहा हूं, सिर्फ शेल लिपियों के खिलाफ जहां ऐसी जटिलता की आवश्यकता है। लेकिन यह सिर्फ मेरी व्यक्तिगत पसंद है; मैं अक्सर खुद को एक शेल स्क्रिप्ट लिखना शुरू करने के लिए पकड़ लेता हूं और फिर तुरंत पर्ल में इसे फिर से लिखना शुरू करता हूं जब मुझे पता चलता है कि मैं एक निश्चित जटिलता सीमा से अधिक हूं।
मार्टिन वॉन विटिच

जवाबों:


20

साहचर्य सरणियों के साथ गोले

कुछ आधुनिक गोले साहचर्य सरणियाँ प्रदान करते हैं: ksh93, bash z4, zsh। Ksh93 और bash में, यदि aएक सहयोगी सरणी है, तो "${!a[@]}"इसकी कुंजियों का सरणी है:

for k in "${!a[@]}"; do
  echo "$k -> ${a[$k]}"
done

Zsh में, वह सिंटैक्स केवल ksh इम्यूलेशन मोड में काम करता है। अन्यथा आपको zsh के मूल सिंटैक्स का उपयोग करना होगा:

for k in "${(@k)a}"; do
  echo "$k -> $a[$k]"
done

${(k)a}aखाली कुंजी नहीं होने पर भी काम करता है।

Zsh में, आप एक ही समय में keys और values दोनों पर लूप कर सकते हैं :

for k v ("${(@kv)a}") echo "$k -> $v"

साहचर्य सरणियों के बिना गोले

गोले में साहचर्य सरणियों का अनुकरण करना जो उनके पास नहीं है वह बहुत अधिक काम है। यदि आपको साहचर्य सरणियों की आवश्यकता है, तो संभवतः यह एक बड़ा उपकरण लाने का समय है, जैसे ksh93 या पर्ल।

यदि आपको केवल POSIX शेल में सहयोगी सरणियों की आवश्यकता है, तो उन्हें अनुकरण करने का एक तरीका है, जब कुंजियों को केवल वर्ण 0-9A-Z_a-z(ASCII अंक, अक्षर और अंडरस्कोर) शामिल करने के लिए प्रतिबंधित किया जाता है । इस धारणा के तहत, चर नाम के भाग के रूप में कुंजियों का उपयोग किया जा सकता है। नीचे दिए गए कार्य एक नामकरण उपसर्ग, "स्टेम" द्वारा पहचाने गए सरणी पर कार्य करते हैं, जिसमें लगातार दो अंडरस्कोर नहीं होना चाहिए।

## ainit STEM
## Declare an empty associative array named STEM.
ainit () {
  eval "__aa__${1}=' '"
}
## akeys STEM
## List the keys in the associatve array named STEM.
akeys () {
  eval "echo \"\$__aa__${1}\""
}
## aget STEM KEY VAR
## Set VAR to the value of KEY in the associative array named STEM.
## If KEY is not present, unset VAR.
aget () {
  eval "unset $3
        case \$__aa__${1} in
          *\" $2 \"*) $3=\$__aa__${1}__$2;;
        esac"
}
## aset STEM KEY VALUE
## Set KEY to VALUE in the associative array named STEM.
aset () {
  eval "__aa__${1}__${2}=\$3
        case \$__aa__${1} in
          *\" $2 \"*) :;;
          *) __aa__${1}=\"\${__aa__${1}}$2 \";;
        esac"
}
## aunset STEM KEY
## Remove KEY from the associative array named STEM.
aunset () {
  eval "unset __aa__${1}__${2}
        case \$__aa__${1} in
          *\" $2 \"*) __aa__${1}=\"\${__aa__${1}%%* $2 } \${__aa__${1}#* $2 }\";;
        esac"
}

(चेतावनी, अनुपयोगी कोड। वाक्य-रचना के अमान्य तनों और कुंजियों के लिए त्रुटि का पता लगाने की अनुमति नहीं दी गई है।)


5

मुझे यकीन नहीं है कि आप स्टोर से क्या मतलब है, लेकिन आप ${!array[@]}सिंटैक्स का उपयोग करके कुंजियों पर पुनरावृति कर सकते हैं :

$ typeset -A foo=([key1]=bar [key2]=baz);
$ echo "${!foo[@]}" 
key2 key1

तो, पुनरावृति करने के लिए:

$ for key in "${!foo[@]}"; do echo "$key : ${foo[$key]}"; done
key2 : baz
key1 : bar

मैं एक अच्छा, इस पर कम ट्यूटोरियल पाया यहाँ


जैसा कि नीचे टिप्पणी में कहा गया है, bashसंस्करण 4 में साहचर्य सरणियों को जोड़ा गया था । इस विषय पर एक लिनक्स जर्नल लेख के लिए यहां देखें ।


1
(bash version 4 only)यह ध्यान देने योग्य बात है। परंपरागत रूप से, bashसरणियाँ केवल संख्यात्मक होती हैं।
रिकी बीम

1
आप अपने उदाहरणों के typesetबजाय उपयोग करना चाह declareसकते हैं। यह उन्हें बैश 4 और ksh93 के बीच पोर्टेबल बना देगा जिसने पहली बार शेल साहचर्य सरणियों को लागू किया था।
जूलियाग्रे

0

साहचर्य सरणियों के बिना गोले

यह मुश्किल नहीं है जब चाबियाँ [0-9A-Za-z_](संख्या, अक्षर, अंडरस्कोर) तक सीमित हैं ।

चाल सरणी [ $ कुंजी ] को संग्रहीत करने के बजाय , चर array_ $ कुंजी के लिए है

सेट:

eval "array_$key='$value'"

प्राप्त:

value=`eval echo '$'array_$key`

नोट: मानों में '(एकल उद्धरण) नहीं हो सकता ।


-1

यह काम करता है

cert="first"
web="second"
declare -A assoc_array=(["cert"]="${cert}" ["web"]="${web}")
echo "first is" ${assoc_array[cert]}
echo "second is" ${assoc_array[web]}

या

#loop
for i in "${assoc_array[@]}"
do
   echo "$i"
done

Eval afaik का उपयोग करने की आवश्यकता नहीं है


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