अनुमेय परिवर्तनशील नाम


12

मैं यह कर सकता हूं, लेकिन इसके लिए चर की एक स्ट्रिंग बनाने की आवश्यकता होती है, फिर इसे डीरफेर करना। क्या एक सरल बयान के लिए इसे छोटा करने का कोई तरीका है?

#!/bin/bash

FRUITS="BANANA APPLE ORANGE"

BANANA_COLOUR="Yellow"
APPLE_COLOUR="Green or Red"
ORANGE_COLOUR="Blue"

for fruit in $( echo $FRUITS ); do
    fruit_colour="${fruit}_COLOUR"
    echo $fruit is ${!fruit_colour}
done

मैंने बहुत सी चीजों की कोशिश की है जैसे कि ${!"${fruit}_COLOUR"}या \$${fruit}_COLOURकई अन्य वेरिएंट, लेकिन एकमात्र तरीका जिसने काम किया है वह एक स्ट्रिंग का उपयोग करके है।


!वाक्य रचना चर प्रतिस्थापन पर एक झंडा मूल रूप से कहना है कि "विकल्प दो बार" है। यह इस आवश्यकता को परिवर्तित नहीं करता है कि ${…}एक चर नाम के अंदर क्या होना चाहिए। तो नहीं, आप एक चर का उपयोग करने से बच सकते हैं जिसमें नाम शामिल है, जब तक कि आप एक अलग विधि ( eval) का उपयोग न करें ।
गिलेस एसओ- बुराई को रोकना '

आप इसे अधिक सफाई से करने के लिए सहयोगी सरणियों का भी उपयोग कर सकते हैं। हालाँकि यह आपके सवाल का सीधा जवाब नहीं है, इसलिए इसे टिप्पणी के रूप में जोड़ दें।
पैट्रिक

जवाबों:


11

सबसे पहले, आपको कथन $(echo $FRUITS)में उपयोग करने की आवश्यकता नहीं है for। सिर्फ उपयोग करना $FRUITSकाफी है। फिर आप लूप के अंदर एक लाइन के साथ, उपयोग करके दूर कर सकते हैं eval

evalबस बैश बताता है एक दूसरे बनाने के लिए मूल्यांकन (यानी एक और अपनी सामान्य मूल्यांकन की तुलना में) निम्नलिखित बयान की। \$के रूप में पहली मूल्यांकन बचता $है, और अगले मूल्यांकन तो यह व्यवहार करता है $एक चर नाम की शुरुआत, के रूप में जो "पीला", आदि ले कर जाता है

इस तरह आपको एक अलग कदम रखने की आवश्यकता नहीं है जो एक अंतरिम स्ट्रिंग बनाता है (जो कि मेरा मानना ​​है कि आपके प्रश्न का मुख्य इरादा था)।

for fruit in $FRUITS ;do
    eval echo $fruit is \$${fruit}_COLOUR
done

एक वैकल्पिक विधि के लिए, जैसा कि एक टिप्पणी में पैट्रिक द्वारा उल्लेख किया गया है , आप इसके बजाय एक साहचर्य सरणी का उपयोग कर सकते हैं , जिसमें किसी तत्व के सूचकांक को पूर्णांक होने की आवश्यकता नहीं है। आप एक स्ट्रिंग का उपयोग कर सकते हैं, जैसे कि एक प्रकार का फल। यहाँ एक उदाहरण है, bash के साहचर्य सरणी का उपयोग करते हुए:

# This declares an associative array (It unsets it if it already exists)
declare -A colour
colour['BANANA']="Yellow"
colour["APPLE"]="Green or Red"
colour[MARTIAN ORANGE]="Blue"

for fruit in BANANA APPLE "MARTIAN ORANGE" ;do 
    echo "$fruit" is "${colour[$fruit]}"
done

6

आप ऐसा करने के लिए बैश-बिलिन evalका उपयोग कर सकते हैं :

#!/bin/bash
FRUITS="BANANA APPLE ORANGE"
BANANA_COLOUR="Yellow"
APPLE_COLOUR="Green or Red"
ORANGE_COLOUR="Blue"

for fruit in $( echo $FRUITS );
do
    fruit_colour=${fruit}_COLOUR
    eval echo $fruit is \$${fruit_colour}
done

बैकस्लेस्ड-डॉलर चिन्ह पर ध्यान दें। मूल रूप से, "eval" लाइन का कारण बनता bash है $fruitऔर ${fruit_color}फिर evalकॉल करने से पहले दूसरे दौर के सबस्टेशन का उपयोग करने के लिए echo


1

आपको एक स्पष्ट कथन की आवश्यकता नहीं है। evalअधिकांश भाषाओं में एक संकेत है कि आप कुछ गलत कर रहे हैं।

foo_var=10
bar_var=12

# Build a string with your var name of choice
chosen_prefix='foo'
var_name="${chosen_prefix}_var"

# Use bang to deference it
chossen_value=${!var_name}
echo "Chossen value: ${chossen_value}"

मेरा तर्क है कि यह उपयोग करने के लिए सुरक्षित है evalक्योंकि कम से कम लोग जानते हैं कि यह खतरनाक है, एक हमलावर के नियंत्रण के तहत (एक कमांड इंजेक्शन भेद्यता के ${!var}रूप में) खतरनाक है और कम लोगों को इसके बारे में पता है। कोशिश करो । यहां सबसे अच्छा दृष्टिकोण सहयोगी सरणी है। bash$chosen_prefixvar_name='a[$(uname>&2)0]' bash -c 'v=${!var_name}'
स्टीफन चेज़लस
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.