DevOps बूटकैंप · पाठ

Functions के बीच Arrays और Associative Maps भेजना

Complex data structures को functions में सुरक्षित रूप से भेजने और वहाँ से प्राप्त करने के लिए namerefs और indirect expansion का उपयोग करें।

पाठ 4, कुल 4 में से13 चरण

Functions के बीच Arrays और Associative Maps भेजना, CoddyKit पर DevOps बूटकैंप का एक निःशुल्क पाठ है। यह 4 में से 4वाँ पाठ है। इस अध्ययन पथ के 3 तक कोई भी पाठ पूरा पढ़ना निःशुल्क है — इसके बाद CoddyKit PRO हर पाठ अनलॉक करता है, साथ ही अंतर्निर्मित कोड संपादक और चौबीसों घंटे एआई शिक्षक के साथ व्यावहारिक अभ्यास भी उपलब्ध कराता है। यह DevOps बूटकैंप सीखने के मार्ग का हिस्सा है और आपकी प्रगति वेब तथा CoddyKit ऐप पर सिंक होती रहती है। DevOps बूटकैंप पाठ्यक्रम में कुल 4 पाठ शामिल हैं।

फ़ंक्शन में ऐरे भेजना कठिन क्यों है

Bash में ऐरे और संबद्ध ऐरे प्रथम-श्रेणी के मान नहीं होते। जब आप किसी फ़ंक्शन में ऐरे भेजने का प्रयास करते हैं, तो आप केवल $my_array का उपयोग नहीं कर सकते — इससे केवल पहला तत्व फैलता है।

इस असफल प्रयास पर ध्यान दें:

my_func "${my_array[@]}"

फ़ंक्शन को शब्दों की एक सपाट सूची मिलती है। उसके पास यह जानने का कोई तरीका नहीं होता कि एक तत्व कहाँ समाप्त होता है और अगला कहाँ शुरू होता है, और ऐरे की पूरी संरचना नष्ट हो जाती है।

Bash जटिल डेटा संरचनाएँ भेजने के लिए दो विश्वसनीय तरीके प्रदान करता है:

  • नाम-संदर्भ (declare -n) — नाम के आधार पर किसी अन्य चर का संदर्भ (Bash 4.3+)
  • अप्रत्यक्ष विस्तार (${!varname[@]}) — ऐसे चर तक पहुँचना जिसका नाम किसी अन्य चर में संग्रहीत है (पुराना Bash)

इस पाठ में दोनों तकनीकों को शामिल किया गया है, ताकि आप ऐरे और मानचित्रों के साथ काम करने वाले मजबूत, पुन: उपयोग योग्य फ़ंक्शन लिख सकें।

नाम-संदर्भ का उपयोग करके नाम से ऐरे भेजना

सबसे साफ़ आधुनिक तरीका नाम-संदर्भ है: आप ऐरे का नाम एक स्ट्रिंग के रूप में भेजते हैं और फ़ंक्शन के भीतर ऐसा स्थानीय चर घोषित करते हैं जो उसका संदर्भ होता है।

मुख्य वाक्य-विन्यास:

  • declare -n ref="$1" — अब ref पहले तर्क के रूप में भेजे गए किसी भी चर-नाम का उपनाम है
  • आप ref को ठीक उसी तरह पढ़ते, दोहराते और संशोधित करते हैं जैसे मूल ऐरे को करते

इससे पूरे ऐरे की प्रतिलिपि बनाने की आवश्यकता नहीं रहती और फ़ंक्शन किसी भी आकार के ऐरे के साथ काम कर सकता है।

#!/usr/bin/env bash

print_array() {
    declare -n arr="$1"   # nameref: arr -> caller's variable
    echo "Array has ${#arr[@]} elements:"
    for elem in "${arr[@]}"; do
        echo "  - $elem"
    done
}

fruits=(apple banana cherry)
print_array fruits

फ़ंक्शन के भीतर कॉल करने वाले का ऐरे संशोधित करना

नाम-संदर्भ वास्तविक उपनाम होने के कारण, नाम-संदर्भ के माध्यम से किए गए लेखन से कॉल करने वाले का मूल चर बदल जाता है। मानों को वापस प्रतिध्वनित करने या वैश्विक चरों का उपयोग करने की आवश्यकता नहीं होती।

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

#!/usr/bin/env bash

to_uppercase() {
    declare -n _arr="$1"
    for i in "${!_arr[@]}"; do
        _arr[$i]="${_arr[$i]^^}"   # ^^ = uppercase in Bash 4+
    done
}

words=(hello world bash)
echo "Before: ${words[@]}"
to_uppercase words
echo "After:  ${words[@]}"

नाम-संदर्भ के माध्यम से नया ऐरे लौटाना

कोई फ़ंक्शन आउटपुट पैरामीटर के रूप में उसका नाम स्वीकार करके कॉल करने वाले द्वारा दिए गए ऐरे में लिख भी सकता है। कॉल करने वाला एक खाली ऐरे बनाता है, उसका नाम भेजता है और फ़ंक्शन उसमें मान भर देता है।

यह तरीका परिणाम-बफ़र के लिए पॉइंटर भेजने की पारंपरिक C शैली से मिलता-जुलता है — अंतर केवल इतना है कि यहाँ यह पूरी तरह शेल में किया जाता है।

#!/usr/bin/env bash

get_even_numbers() {
    local -a source=("$@")
    # Last argument is the output array name — pop it off
    local out_name="${source[-1]}"
    unset 'source[-1]'

    declare -n _out="$out_name"
    _out=()   # clear
    for n in "${source[@]}"; do
        (( n % 2 == 0 )) && _out+=("$n")
    done
}

declare -a evens
get_even_numbers 1 2 3 4 5 6 7 8 evens
echo "Evens: ${evens[@]}"

नाम-संदर्भ टकराव का जाल

नाम-संदर्भों में एक महत्वपूर्ण समस्या है: यदि स्थानीय नाम-संदर्भ चर का नाम कॉल करने वाले के चर के समान हो, तो Bash अनंत स्व-संदर्भ लूप में चला जाता है और स्क्रिप्ट विफल हो जाती है।

उदाहरण के लिए, यदि कॉल करने वाला अपने ऐरे का नाम arr रखता है और फ़ंक्शन declare -n arr="$1" करता है, तो नाम-संदर्भ arr स्वयं की ओर संकेत करता है।

इससे बचने की परंपरा: आंतरिक नाम-संदर्भ चरों के आगे अंडरस्कोर लगाएँ (जैसे, _arr, _ref, _out)। कॉल करने वाले लगभग कभी ऐसे नामों का उपयोग नहीं करते, इसलिए टकराव अत्यंत दुर्लभ होते हैं।

#!/usr/bin/env bash

# DANGER: caller uses variable named 'arr'
arr=(one two three)

bad_func() {
    declare -n arr="$1"   # collision! arr refers to itself
    echo "${arr[@]}"
}

good_func() {
    declare -n _arr="$1"  # underscore prefix avoids collision
    echo "${_arr[@]}"
}

# bad_func arr   # would hang / error
good_func arr

संबद्ध ऐरे (मानचित्र) नाम से भेजना

संबद्ध ऐरे (declare -A) नाम-संदर्भों के साथ बिल्कुल इसी तरह काम करते हैं। मानचित्र का नाम एक स्ट्रिंग के रूप में भेजें और फ़ंक्शन के भीतर नाम-संदर्भ घोषित करें — आपको सभी कुंजी-मान युग्मों तक पूरा पढ़ने-लिखने का अधिकार मिल जाता है।

यह कॉन्फ़िगरेशन मानचित्रों, विकल्प विश्लेषकों और उन खोज-सारिणियों के लिए अत्यंत उपयोगी है जिन्हें पुस्तकालय के कई फ़ंक्शनों के बीच साझा करना होता है।

#!/usr/bin/env bash

print_map() {
    declare -n _map="$1"
    echo "Map contents:"
    for key in "${!_map[@]}"; do
        printf '  %-15s => %s\n' "$key" "${_map[$key]}"
    done
}

declare -A config
config[host]="localhost"
config[port]="5432"
config[db]="myapp"

print_map config

नाम-संदर्भ से दो मानचित्रों को मिलाना

नाम-संदर्भ फ़ंक्शन को सक्रिय उपनाम देते हैं, इसलिए आप मानचित्रों को मिलाने जैसी उपयोगिताएँ साफ़-सुथरे ढंग से बना सकते हैं। गंतव्य मानचित्र और एक या अधिक स्रोत मानचित्रों के नाम भेजें; फ़ंक्शन स्रोत कुंजियों पर दोहराते हुए उन्हें गंतव्य में लिखता है।

नाम-संदर्भों से एक सामान्य merge_map फ़ंक्शन लिखना संभव होता है, जो आपकी स्क्रिप्ट के किसी भी संबद्ध ऐरे पर काम करता है।

#!/usr/bin/env bash

merge_map() {
    # merge_map dest src
    declare -n _dest="$1"
    declare -n _src="$2"
    for key in "${!_src[@]}"; do
        _dest["$key"]="${_src[$key]}"
    done
}

declare -A defaults=([timeout]=30 [retries]=3 [verbose]=false)
declare -A overrides=([retries]=5 [log_level]=debug)

merge_map defaults overrides

for k in "${!defaults[@]}"; do
    echo "$k = ${defaults[$k]}"
done

अप्रत्यक्ष विस्तार: पुराने Bash के साथ संगतता

यदि आपको Bash 4.0–4.2 (या पुराने macOS के डिफ़ॉल्ट शेल) का समर्थन करना आवश्यक है, तो declare -n उपलब्ध नहीं होगा। इसका विकल्प ${!varname} के साथ अप्रत्यक्ष विस्तार है।

अप्रत्यक्ष विस्तार varname के मान का मूल्यांकन चर-नाम के रूप में करता है और उस चर का मान लौटाता है। ऐरे के लिए, सभी तत्व प्राप्त करने हेतु इसे एक विशेष वाक्य-विन्यास के साथ मिलाया जाता है।

नाम-संदर्भों की तुलना में सीमाएँ:

  • व्यवहार में केवल पढ़ने योग्य (वापस लिखने के लिए eval चाहिए, जिसमें इंजेक्शन का जोखिम होता है)
  • eval के बिना संबद्ध ऐरे की कुंजियों पर सुरक्षित रूप से दोहराया नहीं जा सकता
  • जहाँ संभव हो नाम-संदर्भों का उपयोग करें; केवल आवश्यकता होने पर अप्रत्यक्ष विस्तार का विकल्प अपनाएँ
#!/usr/bin/env bash

sum_array() {
    local arr_name="$1"
    # Indirect: build a temporary copy by expanding arr_name[@]
    local -a items
    eval "items=( \"\${${arr_name}[@]}\" )"
    local total=0
    for n in "${items[@]}"; do
        (( total += n ))
    done
    echo "$total"
}

numbers=(10 20 30 40)
result=$(sum_array numbers)
echo "Sum: $result"

मॉड्यूलर स्क्रिप्ट पुस्तकालय बनाना

पेशेवर Bash परियोजनाओं में उपयोगिता फ़ंक्शन पुस्तकालय फ़ाइलों (जैसे, lib/array_utils.sh) में संग्रहीत किए जाते हैं और जिन स्क्रिप्टों को उनकी आवश्यकता होती है, वे उन्हें स्रोतित करती हैं।

पद्धति यह है:

  • हर पुस्तकालय फ़ाइल केवल फ़ंक्शन परिभाषित करती है — शीर्ष-स्तरीय दुष्प्रभाव नहीं करती
  • एक संकेतक चर से दोहरी स्रोत-संग्रहण रोकें: [[ -n $__LIB_LOADED ]] && return; __LIB_LOADED=1
  • उपभोक्ता स्क्रिप्ट पुस्तकालय लोड करने के लिए source या . का उपयोग करती हैं
  • फ़ंक्शन नाम-संदर्भों के माध्यम से जटिल डेटा का आदान-प्रदान करते हैं, जिससे पूरा तर्क स्व-निहित रहता है

इससे ऐसी स्क्रिप्ट बनती हैं जिनका परीक्षण, पुन: उपयोग और रखरखाव किया जा सकता है — न कि केवल एक बार काम आने वाली शेल तरकीबें।

व्यावहारिक उदाहरण: मानचित्र लौटाने वाला विकल्प विश्लेषक

वास्तविक उपयोग का एक उदाहरण: कमांड-लाइन विकल्प विश्लेषक, जो कॉल करने वाले द्वारा दिए गए संबद्ध ऐरे में मान भरता है। कॉल करने वाला पहले तर्क के रूप में ऐरे का नाम और उसके बाद वास्तविक "$@" तर्क भेजता है।

इस पद्धति से कोई भी स्क्रिप्ट कोड की प्रतिलिपि बनाए बिना या वैश्विक चरों पर निर्भर हुए बिना उसी विश्लेषक का पुन: उपयोग कर सकती है।

#!/usr/bin/env bash

parse_opts() {
    declare -n _opts="$1"
    shift
    while [[ $# -gt 0 ]]; do
        case "$1" in
            --host)   _opts[host]="$2";   shift 2 ;;
            --port)   _opts[port]="$2";   shift 2 ;;
            --user)   _opts[user]="$2";   shift 2 ;;
            *)        echo "Unknown option: $1" >&2; shift ;;
        esac
    done
}

declare -A opts=([host]=localhost [port]=5432 [user]=admin)
parse_opts opts --host db.example.com --port 3306

echo "Connecting to ${opts[host]}:${opts[port]} as ${opts[user]}"

एक फ़ंक्शन में इनपुट और आउटपुट नाम-संदर्भों को मिलाना

फ़ंक्शन एक साथ कई नाम-संदर्भ रख सकते हैं — एक इनपुट के लिए और एक आउटपुट के लिए। इससे शुद्ध रूपांतरण फ़ंक्शन संभव होते हैं: वे स्रोत संरचना से पढ़ते हैं, परिणाम की गणना करते हैं और उसे गंतव्य संरचना में लिखते हैं, वह भी वैश्विक स्थिति को छुए बिना।

हर नाम-संदर्भ के लिए अलग-अलग अंडरस्कोर-युक्त नाम रखने से टकराव असंभव हो जाते हैं, भले ही कॉल करने वाले के चरों के नाम साधारण हों।

#!/usr/bin/env bash

filter_map_by_key_prefix() {
    # Usage: filter_map_by_key_prefix src_map dest_map prefix
    declare -n _src="$1"
    declare -n _dst="$2"
    local prefix="$3"

    _dst=()
    for key in "${!_src[@]}"; do
        if [[ $key == ${prefix}* ]]; then
            _dst["$key"]="${_src[$key]}"
        fi
    done
}

declare -A settings=(
    [db_host]=localhost [db_port]=5432
    [cache_ttl]=300     [cache_driver]=redis
    [app_debug]=true
)
declare -A db_settings

filter_map_by_key_prefix settings db_settings db_

for k in "${!db_settings[@]}"; do
    echo "$k = ${db_settings[$k]}"
done

ज्ञान-जाँच: नाम-संदर्भ और ऐरे भेजना

Bash में फ़ंक्शनों के बीच ऐरे और मानचित्र भेजने की अपनी समझ जाँचें।

पुनरावलोकन: Bash में जटिल डेटा संरचनाएँ भेजना

इस पाठ में आपने यह सीखा:

  • ऐरे को मान के रूप में नहीं भेजा जा सकता — इसके बजाय चर का नाम एक स्ट्रिंग के रूप में भेजें।
  • declare -n ref="$varname" नाम-संदर्भ बनाता है: कॉल करने वाले के चर का सक्रिय उपनाम। पढ़ना और लिखना दोनों मूल चर तक पहुँचते हैं। इसके लिए Bash 4.3+ आवश्यक है।
  • नाम-संदर्भ टकराव तब होता है जब आंतरिक और बाहरी चर का नाम समान हो। आंतरिक नाम-संदर्भों के आगे उपसर्ग लगाकर इसे रोकें (जैसे, _arr, _map)।
  • आउटपुट पैरामीटर किसी खाली परिणाम ऐरे या मानचित्र का नाम भेजकर काम करते हैं; फ़ंक्शन नाम-संदर्भ के माध्यम से उसमें मान भरता है।
  • एक फ़ंक्शन में कई नाम-संदर्भ वैश्विक दुष्प्रभावों के बिना शुद्ध इनपुट-से-आउटपुट रूपांतरण संभव बनाते हैं।
  • अप्रत्यक्ष विस्तार (${!varname[@]} + eval) Bash < 4.3 के लिए पुराना वैकल्पिक उपाय है, लेकिन इसमें इंजेक्शन का जोखिम होता है और व्यवहार में यह केवल पढ़ने योग्य है।
  • मॉड्यूलर, पुन: उपयोग योग्य और परीक्षण योग्य Bash कोड-आधार बनाने के लिए इन तकनीकों को स्रोतित पुस्तकालय फ़ाइलों के साथ मिलाएँ।
शुरुआत निःशुल्क

एआई शिक्षक के साथ DevOps बूटकैंप सीखें — निःशुल्क

अपने ब्राउज़र में वास्तविक कोड लिखें और चलाएँ, चौबीसों घंटे एआई शिक्षक से तुरंत सहायता पाएँ, और वेब या ऐप पर वहीं से शुरू करें जहाँ आपने छोड़ा था।

पाठ्यक्रम
142
पाठ
568

अक्सर पूछे जाने वाले प्रश्न

क्या “Functions के बीच Arrays और Associative Maps भेजना” पाठ निःशुल्क है?

हाँ — DevOps बूटकैंप अध्ययन पथ के 3 तक कोई भी पाठ, जिसमें “Functions के बीच Arrays और Associative Maps भेजना” भी शामिल है, यहाँ वेब पर पूरा पढ़ना निःशुल्क है। इसके बाद CoddyKit PRO हर पाठ अनलॉक करता है, साथ ही अंतर्निर्मित कोड संपादक और चौबीसों घंटे एआई शिक्षक के साथ इंटरैक्टिव अभ्यास भी उपलब्ध कराता है। DevOps बूटकैंप पाठ्यक्रम में कुल 4 पाठ शामिल हैं।

“Functions के बीच Arrays और Associative Maps भेजना” में मैं क्या सीखूँगा?

Complex data structures को functions में सुरक्षित रूप से भेजने और वहाँ से प्राप्त करने के लिए namerefs और indirect expansion का उपयोग करें। आप ब्राउज़र में सीधे चलाए जाने वाले व्यावहारिक कोड के साथ DevOps बूटकैंप का अभ्यास करते हैं, और पाठ पूरा करते समय 24/7 एआई ट्यूटर आपके प्रश्नों के उत्तर देता है।

क्या DevOps बूटकैंप शुरू करने के लिए मुझे किसी अनुभव की आवश्यकता है?

पहले के अनुभव की आवश्यकता नहीं है। CoddyKit पर DevOps बूटकैंप शुरुआती से लेकर उन्नत शिक्षार्थियों तक सभी के लिए व्यवस्थित किया गया है, इसलिए आप यहीं से या शुरुआत से सीखना शुरू कर सकते हैं और अपनी गति से आगे बढ़ सकते हैं। यह 4 में से 4वाँ पाठ है।

“Functions के बीच Arrays और Associative Maps भेजना” पाठ पूरा करने में कितना समय लगता है?

CoddyKit का अधिकांश पाठ लगभग 5–10 मिनट में पूरा हो जाता है। हर पाठ छोटा और संवादात्मक है, इसलिए आप लगातार प्रगति करते हैं और वेब या ऐप पर वहीं से सीखना जारी रख सकते हैं जहाँ आपने छोड़ा था।

क्या मैं इस DevOps बूटकैंप पाठ में कोड लिख और चला सकता हूँ?

हाँ। हर DevOps बूटकैंप पाठ में एक अंतर्निर्मित कोड संपादक शामिल है, जिससे आप सीधे अपने ब्राउज़र में वास्तविक कोड लिख और चला सकते हैं और तुरंत एआई प्रतिक्रिया पा सकते हैं—स्थानीय सेटअप की आवश्यकता नहीं है।

इस पाठ्यक्रम के सभी पाठ

  1. Local Scope और Return Codes से Functions का डिज़ाइन
  2. Reusable Bash Libraries बनाना और Source करना
  3. getopts से Flags और Arguments को Parse करना
  4. Functions के बीच Arrays और Associative Maps भेजना
← DevOps बूटकैंप पर वापस जाएँ