प्रश्न का संक्षिप्त विवरण:
क्या बाश सरणी में तत्वों की संख्या की गणना करने के लिए अंतर्निहित बैश विधि है, जहां सरणी का नाम डायनामिक है (अर्थात एक चर में संग्रहीत), बिना सरणी की पूरी तरह से प्रतिलिपि बनाने या उपयोग करने के लिए eval
?
अधिक जानकारी:
बैश पैरामीटर प्रतिस्थापन का उपयोग करना, एक निम्नलिखित कर सकता है:
- एक सरणी की लंबाई निर्धारित करें
myArr=(A B C); echo ${#myArr[@]}
:। - परोक्ष रूप से नाम से एक चर का संदर्भ:
NAME=myVar; echo ${!NAME}
(यह भी सरणी तत्वों पर लागू होता है):
NAME=myArr[1]; echo ${!NAME}
लेकिन अगर एक सरणी का नाम दूसरे चर में संग्रहीत किया जाता है, तो कोई सरणी में तत्वों की संख्या कैसे निर्धारित कर सकता है? (कोई इसे उपरोक्त दो पैरामीटर प्रतिस्थापन के संयोजन पर विचार कर सकता है ।) उदाहरण के लिए:
myArr=(A B C D)
NAME=myArr
# Get the number of elements in the array indirectly referenced by NAME.
count=${#$NAME[@]} # This syntax is invalid. What is the right way?
नीचे कई प्रयास हैं जो सभी विफल हैं:
# Setup for following attempts:
myArr=(A B C D)
NAME=myArr
EXPR1=$NAME[@] # i.e. EXPR1='myArr[@]'
EXPR2=#$NAME[@] # i.e. EXPR2='#myArr[@]'
# Failed attempts to get the lengh of the array indirectly:
1. count=${#$NAME[@]} # ERROR: bash: ...: bad substitution
2. count=${#!EXPR1} # ERROR: bash: !EXPR}: event not found
3. count=${#\!EXPR1} # ERROR: bash: ...: bad substitution
4. count=${!#EXPR1} # ERROR: bash: ...: bad substitution
5. count=${!EXPR2} # Returns NULL
मैंने ऊपर के कुछ अन्य वेरिएंट भी आज़माए हैं, लेकिन अभी तक ऐसा कुछ भी नहीं पाया है जो या तो बिना काम करे: (ए) का उपयोग करके सरणी (बी) की एक प्रति बना रहा हो eval
।
काम करने के तरीके:
इसे हल करने के कुछ तरीके हैं जो शायद इष्टतम नहीं हैं (लेकिन मुझे गलत होने पर सही करें):
विधि 1: सरणी की प्रतिलिपि बनाएँ
सरणी को दूसरे (स्टैटिस्टिकल-नेम) वेरिएबल में असाइन करें और इसमें तत्वों की संख्या प्राप्त करें।
EXPR=$NAME[@]
arrCopy=( "${!EXPR}" )
count=${#arrCopy}
विधि 2: का उपयोग करें eval
EXPR="count=\${#$NAME[@]}" # i.e. 'count=${myArr[@]}'
eval $EXPR
# Now count is set to the length of the array
सारांश:
अप्रत्यक्ष रूप से किसी सरणी की लंबाई निर्धारित करने के लिए क्या कोई अंतर्निहित विधि (यानी पैरामीटर प्रतिस्थापन सिंटैक्स) है? यदि नहीं, तो ऐसा करने का सबसे कारगर तरीका क्या है? मुझे लगता है कि यह eval
ऊपर की विधि है, लेकिन क्या सुरक्षा या प्रदर्शन के मुद्दे हैं eval
?
time bash -c 'a=(1 a +); c=a; for ((i=0;i<100000;i++)); do eval "echo \${#$c[@]}"; done' > /dev/null
और इसी तरह e=$c[@]; d=("${!e}); echo ${#d[@]}
लूप में। निष्कासन को नकल करने में लगभग 90% समय लगा। और मुझे लगता है कि अंतर केवल बड़े सरणी और उसके तत्वों को बढ़ाएगा।