किसी सरणी नाम के भाग के रूप में एक चर का उपयोग कैसे करें


11

मेरे पास दो सरणियाँ हैं:

arrayA=(1 2 3)
arrayB=(a b c)

और मैं कमांड लाइन तर्क का उपयोग करके उनमें से एक को प्रिंट करना चाहता हूं, अर्थात, बिना किसी के if else

मैंने बिना किसी सफलता के वाक्य रचना पर कुछ बदलावों की कोशिश की। मैं कुछ इस तरह करना चाहता हूं:

ARG="$1"

echo ${array${ARG}[@]}

लेकिन मुझे "खराब प्रतिस्थापन" त्रुटि मिलती है। इसे कैसे प्राप्त किया जा सकता है?


यह सशक्त रूप से मुहावरेदार नहीं है । कृपया, यह मत करो।
वाइल्डकार्ड

जवाबों:


22

ऐसा करने का प्रयास करें:

$ arrayA=(1 2 3)
$ x=A
$ var=array$x[@]
$ echo ${!var}
1 2 3

ध्यान दें

  • से man bash(पैरामीटर विस्तार):
    ${parameter}
           The value of parameter is substituted.
 The braces are required when parameter is a positional parameter with
  more than one

अंक, या जब पैरामीटर एक चरित्र द्वारा पीछा किया जाता है जिसे इसके नाम के हिस्से के रूप में व्याख्या नहीं किया जाना है।
* यदि पैरामीटर का पहला वर्ण विस्मयादिबोधक बिंदु (!) है, तो चर अप्रत्यक्ष का एक स्तर पेश किया जाता है। बैश बाकी पैरामीटर से गठित चर के मूल्य का उपयोग करता है, चर के नाम के रूप में; इस चर का फिर विस्तार किया जाता है और उस मूल्य का उपयोग बाकी सबस्टेशन में किया जाता है, बजाय पैरामीटर के मूल्य के। इसे अप्रत्यक्ष विस्तार के रूप में जाना जाता है। * इसके अपवाद $ {! उपसर्ग *} और $ {! [@]} का विस्तार नीचे वर्णित हैं। विस्मयादिबोधक बिंदु को अप्रत्यक्ष रूप से पेश करने के लिए तुरंत बाएं ब्रेस का पालन करना चाहिए।


वास्तव !में varचर के सामने क्या कर रहा है ? यह कैसे काम करता है, यह googling पर इतिहास प्रतिस्थापन लगता था, लेकिन मैं यह नहीं देख सकता था कि यहां कैसे काम किया गया।
आरोन

मेरी संपादित पोस्ट देखें
गिल्स केनॉट

4

जबकि आप एक अन्य उत्तर में बताए गए अप्रत्यक्ष उपयोग का उपयोग कर सकते हैं , दूसरा तरीका (ksh और बैश 4.3 और नए में) namerefs का उपयोग करना होगा। विशेष रूप से सरणियों के मामले में यह अधिक उपयोगी हो सकता है क्योंकि आप नेमरे के माध्यम से सरणी को अनुक्रमित कर सकते हैं और संदर्भ के रूप में उपयोग किए जाने वाले चर में सूचकांक को डालने की आवश्यकता नहीं है।

arr1=(a b c)
arr2=(x y z)
typeset -n p=arr1    # or 'declare -n' 
echo "${p[1]}"       # prints 'b'

यह अप्रत्यक्ष पहुंच के माध्यम से काम नहीं करता है:

q=arr2
echo "${!q}"         # prints 'x', the same as $arr2
echo "${!q[1]}"      # doesn't work, it tries to take q[1] as a reference

सी प्रोग्रामर के रूप में इसे रखा जा सकता है, ${!q[1]}यहाँ qएक सरणी के लिए एक पॉइंटर होने के बजाय पॉइंटर्स की एक सरणी के रूप में कार्य करता है ।



1
arrayA=(1 2 3)
arrayB=(a b c)

ARG="$1"

eval echo \${array${ARG}[@]}

dataget (){ 
    eval echo \${array${1}[${2:-@}]}
}
$ dataget A
1 2 3
$ dataget A 0
1
$ dataget B 1
b

नोट: अंतरिक्ष के मामले में बच गए !

eval dostuff \"\${array${1}[${2:-@}]}\"

1

इसने बहुत परीक्षण और त्रुटि की लेकिन अंततः काम किया।

मैंने यूनुस से कुछ प्रेरणा ली। लेकिन अन्य सभी उत्तरों ने मेरे पुराने बैश (suse11sp1 [3.2.51 (1) -release) पर मदद नहीं की)

'फॉर' लूप ने अप्रत्यक्ष सरणी का विस्तार करने से इंकार कर दिया, इसके बजाय आपको इसे पूर्व-विस्तारित करने की आवश्यकता है, इसका उपयोग अपने दूसरे चर नाम के साथ एक और सरणी बनाने के लिए करें। नीचे मेरा उदाहरण एक डबल लूप दिखाता है, जैसा कि मेरा इच्छित उपयोग है।

THEBIGLOOP=(New_FOO New_BAR)

FOOthings=(1 2 3)
BARthings=(a b c)

for j in ${THEBIGLOOP[*]}
do
    TheNewVariable=$(eval echo \${${j#New_}things[@]})

    for i in $TheNewVariable
        do
            echo  $j $i" hello"
        echo
    done
done

मैं पहली सरणी प्रविष्टि से "New_" को हटाने के लिए # का उपयोग कर रहा हूं, फिर "FOOthings" प्राप्त करने के लिए, "चीजों" के साथ संक्षिप्त कर रहा हूं। प्रतिध्वनि और निष्कासन के साथ $ {}, फिर त्रुटियों को फेंकने के बिना उनकी बात करें, जिसे एक नए $ () में लपेटा गया है और नया चर नाम सौंपा गया है।

$ Test.sh

New_FOO 1 hello

New_FOO 2 hello

New_FOO 3 hello

New_BAR a hello

New_BAR b hello

New_BAR c hello
UPDATE ##### 2018/06/07

मैंने हाल ही में इस मुद्दे पर एक और स्पिन की खोज की है। बनाया गया चर वास्तव में एक सरणी नहीं है, लेकिन एक अंतरिक्ष सीमांकित स्ट्रिंग है। इसके ऊपर के कार्य के लिए यह ठीक था, क्योंकि "कैसे" काम करता है, यह सरणी को नहीं पढ़ता है, इसका विस्तार किया जाता है और फिर इसके माध्यम से लूप किया जाता है, नीचे देखें:

for VARIABLE in 1 2 3 4 5 .. N
do
    command1
    command2
    commandN
done

लेकिन, मुझे तब इसे एक सरणी के रूप में उपयोग करने की आवश्यकता थी। इसके लिए मुझे एक और कदम उठाने की जरूरत थी। मैंने डेनिस विलियमसन द्वारा कोड वर्बेटिम लिया । मैंने इसका परीक्षण किया है और यह ठीक काम करता है।

IFS=', ' read -r -a TheNewVariable <<< ${TheNewVariable[@]}

"IFS = ','" आपके परिसीमन वाला एक चर है। "-a" के साथ "रीड" कट और सरणी चर में स्टिंग वापस खिलाती है। ध्यान दें, यह उद्धरण चिह्नों के लिए कोई सम्मान नहीं है, लेकिन इसे प्रबंधित करने के लिए पढ़ने में कुछ विकल्प हैं , उदाहरण के लिए मैंने -r ध्वज को हटा दिया है जिसकी मुझे आवश्यकता नहीं थी। इसलिए मैंने अब इसे वैरिएबल क्रिएशन में जोड़ दिया है, जिससे डेटा को ट्रीट किया जा सकता है और इसे उसी तरह से संबोधित किया जाना चाहिए जैसा कि इसे करना चाहिए।

THEBIGLOOP=(New_FOO New_BAR)

FOOthings=(1 2 3)
BARthings=(a b c)

for j in ${THEBIGLOOP[*]}
do

    IFS=', ' read -a TheNewVariable <<< $(eval echo \${${j#New_}things[@]})

    for i in ${TheNewVariable[@]}  #Now have to wrap with {} and expand with @
        do
            echo  $j $i" hello"
            echo  ${TheNewVariable[$i]}  #This would not work in the original code
        echo
    done
done

0

यह है कि आप एक डायनामिक रूप से नामित चर (bash संस्करण <4.3) कैसे बनाएंगे।

# Dynamically named array
my_variable_name="dyn_arr_names"
eval $my_variable_name=\(\)

# Adding by index to the array eg. dyn_arr_names[0]="bob"
eval $my_variable_name[0]="bob"

# Adding by pushing onto the array eg. dyn_arr_names+=(robert)
eval $my_variable_name+=\(robert\)

# Print value stored at index indirect
echo ${!my_variable_name[0]}

# Print value stored at index
eval echo \${$my_variable_name[0]}

# Get item count
eval echo \${#$my_variable_name[@]}

नीचे फ़ंक्शंस का एक समूह है, जिसका उपयोग गतिशील रूप से नामित सरणियों को प्रबंधित करने के लिए किया जा सकता है (bash संस्करण <4.3)।

# Dynamically create an array by name
function arr() {
    [[ ! "$1" =~ ^[a-zA-Z_]+[a-zA-Z0-9_]*$ ]] && { echo "Invalid bash variable" 1>&2 ; return 1 ; }
     # The following line can be replaced with 'declare -ag $1=\(\)'
     # Note: For some reason when using 'declare -ag $1' without the parentheses will make 'declare -p' fail
    eval $1=\(\)
}

# Insert incrementing by incrementing index eg. array+=(data)
function arr_insert() { 
    [[ ! "$1" =~ ^[a-zA-Z_]+[a-zA-Z0-9_]*$ ]] && { echo "Invalid bash variable" 1>&2 ; return 1 ; }
    declare -p "$1" > /dev/null 2>&1
    [[ $? -eq 1 ]] && { echo "Bash variable [${1}] doesn't exist" 1>&2 ; return 1 ; }
    eval $1[\$\(\(\${#${1}[@]}\)\)]=\$2
}

# Update an index by position
function arr_set() {
    [[ ! "$1" =~ ^[a-zA-Z_]+[a-zA-Z0-9_]*$ ]] && { echo "Invalid bash variable" 1>&2 ; return 1 ; }
    declare -p "$1" > /dev/null 2>&1
    [[ $? -eq 1 ]] && { echo "Bash variable [${1}] doesn't exist" 1>&2 ; return 1 ; }
    eval ${1}[${2}]=\${3}
}

# Get the array content ${array[@]}
function arr_get() {
    [[ ! "$1" =~ ^[a-zA-Z_]+[a-zA-Z0-9_]*$ ]] && { echo "Invalid bash variable" 1>&2 ; return 1 ; }
    declare -p "$1" > /dev/null 2>&1
    [[ $? -eq 1 ]] && { echo "Bash variable [${1}] doesn't exist" 1>&2 ; return 1 ; }
    eval echo \${${1}[@]}
}

# Get the value stored at a specific index eg. ${array[0]}  
function arr_at() {
    [[ ! "$1" =~ ^[a-zA-Z_]+[a-zA-Z0-9_]*$ ]] && { echo "Invalid bash variable" 1>&2 ; return 1 ; }
    declare -p "$1" > /dev/null 2>&1
    [[ $? -eq 1 ]] && { echo "Bash variable [${1}] doesn't exist" 1>&2 ; return 1 ; }
    [[ ! "$2" =~ ^(0|[-]?[1-9]+[0-9]*)$ ]] && { echo "Array index must be a number" 1>&2 ; return 1 ; }
    local v=$1
    local i=$2
    local max=$(eval echo \${\#${1}[@]})
    # Array has items and index is in range
    if [[ $max -gt 0 && $i -ge 0 && $i -lt $max ]]
    then 
        eval echo \${$v[$i]}
    fi
}

# Get the value stored at a specific index eg. ${array[0]}  
function arr_count() {
    [[ ! "$1" =~ ^[a-zA-Z_]+[a-zA-Z0-9_]*$ ]] && { echo "Invalid bash variable " 1>&2 ; return 1 ; }
    declare -p "$1" > /dev/null 2>&1
    [[ $? -eq 1 ]] && { echo "Bash variable [${1}] doesn't exist" 1>&2 ; return 1 ; }
    local v=${1}
    eval echo \${\#${1}[@]}
}



array_names=(bob jane dick)

for name in "${array_names[@]}"
do
    arr dyn_$name
done

echo "Arrays Created"
declare -a | grep "a dyn_"

# Insert three items per array
for name in "${array_names[@]}"
do
    echo "Inserting dyn_$name abc"
    arr_insert dyn_$name "abc"
    echo "Inserting dyn_$name def"
    arr_insert dyn_$name "def"
    echo "Inserting dyn_$name ghi"
    arr_insert dyn_$name "ghi"
done

for name in "${array_names[@]}"
do
    echo "Setting dyn_$name[0]=first"
    arr_set dyn_$name 0 "first"
    echo "Setting dyn_$name[2]=third"
    arr_set dyn_$name 2 "third"
done 

declare -a | grep "a dyn_"

for name in "${array_names[@]}"
do
    arr_get dyn_$name
done


for name in "${array_names[@]}"
do
    echo "Dumping dyn_$name by index"
    # Print by index
    for (( i=0 ; i < $(arr_count dyn_$name) ; i++ ))
    do
        echo "dyn_$name[$i]: $(arr_at dyn_$name $i)"

    done
done

for name in "${array_names[@]}"
do
    echo "Dumping dyn_$name"
    for n in $(arr_get dyn_$name)
    do
        echo $n
    done
done

नीचे फ़ंक्शंस का एक समूह है जिसका उपयोग गतिशील रूप से नामित सरणियों को प्रबंधित करने के लिए किया जा सकता है (bash संस्करण> = 4.3)।

# Dynamically create an array by name
function arr() {
    [[ ! "$1" =~ ^[a-zA-Z_]+[a-zA-Z0-9_]*$ ]] && { echo "Invalid bash variable" 1>&2 ; return 1 ; }
    declare -g -a $1=\(\)   
}

# Insert incrementing by incrementing index eg. array+=(data)
function arr_insert() { 
    [[ ! "$1" =~ ^[a-zA-Z_]+[a-zA-Z0-9_]*$ ]] && { echo "Invalid bash variable" 1>&2 ; return 1 ; }
    declare -p "$1" > /dev/null 2>&1
    [[ $? -eq 1 ]] && { echo "Bash variable [${1}] doesn't exist" 1>&2 ; return 1 ; }
    declare -n r=$1
    r[${#r[@]}]=$2
}

# Update an index by position
function arr_set() {
    [[ ! "$1" =~ ^[a-zA-Z_]+[a-zA-Z0-9_]*$ ]] && { echo "Invalid bash variable" 1>&2 ; return 1 ; }
    declare -p "$1" > /dev/null 2>&1
    [[ $? -eq 1 ]] && { echo "Bash variable [${1}] doesn't exist" 1>&2 ; return 1 ; }
    declare -n r=$1 
    r[$2]=$3
}

# Get the array content ${array[@]}
function arr_get() {
    [[ ! "$1" =~ ^[a-zA-Z_]+[a-zA-Z0-9_]*$ ]] && { echo "Invalid bash variable" 1>&2 ; return 1 ; }
    declare -p "$1" > /dev/null 2>&1
    [[ $? -eq 1 ]] && { echo "Bash variable [${1}] doesn't exist" 1>&2 ; return 1 ; }
    declare -n r=$1 
    echo ${r[@]}
}

# Get the value stored at a specific index eg. ${array[0]}  
function arr_at() {
    [[ ! "$1" =~ ^[a-zA-Z_]+[a-zA-Z0-9_]*$ ]] && { echo "Invalid bash variable" 1>&2 ; return 1 ; }
    declare -p "$1" > /dev/null 2>&1
    [[ $? -eq 1 ]] && { echo "Bash variable [${1}] doesn't exist" 1>&2 ; return 1 ; }
    [[ ! "$2" =~ ^(0|[-]?[1-9]+[0-9]*)$ ]] && { echo "Array index must be a number" 1>&2 ; return 1 ; }
    declare -n r=$1 
    local max=${#r[@]}
    # Array has items and index is in range
    if [[ $max -gt 0 && $i -ge 0 && $i -lt $max ]]
    then 
        echo ${r[$2]}
    fi
}

# Get the value stored at a specific index eg. ${array[0]}  
function arr_count() {
    [[ ! "$1" =~ ^[a-zA-Z_]+[a-zA-Z0-9_]*$ ]] && { echo "Invalid bash variable " 1>&2 ; return 1 ; }
    declare -p "$1" > /dev/null 2>&1
    [[ $? -eq 1 ]] && { echo "Bash variable [${1}] doesn't exist" 1>&2 ; return 1 ; }
    declare -n r=$1
    echo ${#r[@]}
}



array_names=(bob jane dick)

for name in "${array_names[@]}"
do
    arr dyn_$name
done

echo "Arrays Created"
declare -a | grep "a dyn_"

# Insert three items per array
for name in "${array_names[@]}"
do
    echo "Inserting dyn_$name abc"
    arr_insert dyn_$name "abc"
    echo "Inserting dyn_$name def"
    arr_insert dyn_$name "def"
    echo "Inserting dyn_$name ghi"
    arr_insert dyn_$name "ghi"
done

for name in "${array_names[@]}"
do
    echo "Setting dyn_$name[0]=first"
    arr_set dyn_$name 0 "first"
    echo "Setting dyn_$name[2]=third"
    arr_set dyn_$name 2 "third"
done 

declare -a | grep 'a dyn_'

for name in "${array_names[@]}"
do
    arr_get dyn_$name
done


for name in "${array_names[@]}"
do
    echo "Dumping dyn_$name by index"
    # Print by index
    for (( i=0 ; i < $(arr_count dyn_$name) ; i++ ))
    do
        echo "dyn_$name[$i]: $(arr_at dyn_$name $i)"

    done
done

for name in "${array_names[@]}"
do
    echo "Dumping dyn_$name"
    for n in $(arr_get dyn_$name)
    do
        echo $n
    done
done

इन उदाहरणों के बारे में अधिक जानकारी के लिए लुडविक जेरेबेक द्वारा डायनामिक एरर्स द्वारा गेटिंग बीशेड पर जाएँ


1
मैं उत्सुक हूं कि यह क्यों घट गया। क्या दृष्टिकोण के साथ कुछ गलत / खतरनाक है। बाश <4.3 पर कार्यों का उपयोग करना चाहेंगे।
स्टीफनम

मैं आपकी पोस्ट की सराहना करता हूं, मुझे उपयोगी जानकारी मिली और विशेष रूप से "आइटम नंबर प्राप्त करें" निर्देश: eval echo \ $ {# $ my_variable_name [@]}
डैनियल पेरेज़

-1

बिल्कुल नहीं :(

यदि आपके सरणियाँ सरल हैं, तो सहयोगी सरणियों का उपयोग करें

    declare -A array
    array[A]="1 2 3"
    array[B]="a b c"

दुर्भाग्य से, यदि आपके सरणियाँ अधिक जटिल हैं (उदाहरण के लिए array=( "a b" c )), तो यह काम नहीं करेगा। फिर, आपको अपने लक्ष्य तक पहुंचने के लिए दूसरे तरीके के बारे में और अधिक सोचने की आवश्यकता है।


पतन का कारण क्या है? साहचर्य सरणी सब कुछ समूहीकृत करने का एक अच्छा तरीका प्रदान करती है, यह मानते हुए कि मेरे तत्वों में कोई स्थान नहीं होगा।
आरोन

2
@Aaron मान लें कि आपके तत्वों में रिक्त स्थान नहीं हैं, यह एक उचित डिज़ाइन है। Noवाताएल मुझे लगता है कि उत्तर का उत्तर "कोई रास्ता नहीं" है जब आपके प्रश्न का प्राथमिक ध्यान स्पष्ट रूप से संभव है, एक अच्छा विचार नहीं था।
गिल्स एसओ- बुराई को रोकना '

-1

उपयोग eval

arrayA=(1 2 3)
ARG=arrayA
eval echo \${$ARG[@]} # equivalent to eval echo \${arrayA[@]}
                      # note that we escape the first '$' to prevent from 
                      # its parameter expansion before passing it to echo
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.