बैश पॉइंटर्स का उपयोग करने के लिए समर्थन प्रदान करता है?


12

आसान सवाल। क्या शेल स्क्रिप्ट लिखते समय पॉइंटर्स का उपयोग करने के लिए बैश शेल का कोई समर्थन है?

मैं विस्तार संकेतन से परिचित हूं, ${var[@]}जब $varयह सरणी पर पुनरावृत्ति करता है , लेकिन यह स्पष्ट नहीं है कि यह सरणी सूचकांकों पर पुनरावृति करने के लिए संकेत का उपयोग कर रहा है। क्या बैश अन्य भाषाओं की तरह मेमोरी एड्रेस तक पहुंच प्रदान करता है?

यदि बैश पॉइंटर्स का उपयोग करने का समर्थन नहीं करता है, तो अन्य गोले क्या करते हैं?

जवाबों:


28

एक पॉइंटर ( मेमोरी के स्थान पर ) वास्तव में C से उच्चतर स्तर की किसी भी चीज़ में एक उपयोगी अवधारणा नहीं है, जैसा कि यह पायथन या शेल जैसा कुछ है। ऑब्जेक्ट्स के संदर्भ उच्च-स्तरीय भाषाओं में उपयोगी होते हैं, शायद जटिल डेटा संरचनाओं के निर्माण के लिए भी आवश्यक होते हैं। लेकिन ज्यादातर मामलों में स्मृति पतों के संदर्भ में सोचना बहुत उपयोगी होने के लिए निम्न स्तर है।

बैश (और अन्य गोले) में, आप ${array[index]}संकेतन के साथ सरणी तत्वों के मान प्राप्त कर सकते हैं , उन्हें असाइन कर सकते हैं और सरणी में तत्वों array[index]=...की संख्या प्राप्त कर सकते हैं ${#array[@]}। कोष्ठक के अंदर की अभिव्यक्ति एक अंकगणितीय अभिव्यक्ति है। एक बने हुए उदाहरण के रूप में, हम सभी सरणी सदस्यों के लिए एक निरंतर उपसर्ग जोड़ सकते हैं:

for ((i=0 ; i < ${#array[@]} ; i++ )) ; do
    array[i]="foo-${array[i]}"
done

(यदि हम केवल मूल्यों की परवाह करते हैं, और अनुक्रमित नहीं, तो बस for x in "${array[@]}" ; do...ठीक होगा।)

साथ साहचर्य या विरल सरणियों , एक संख्यात्मक पाश ज्यादा मतलब नहीं है, लेकिन इसके बजाय हम साथ सरणी कुंजी / अनुक्रमित लाने के लिए आवश्यकता होगी ${!array[@]}। उदाहरण के लिए

declare -A assoc=([foo]="123" [bar]="456")
for i in "${!assoc[@]}" ; do 
    echo "${assoc[$i]}"
done 

इसके अलावा, बैश के पास दूसरे चर के लिए अप्रत्यक्ष रूप से इंगित करने के दो तरीके हैं:

  • सिंटैक्स का उपयोग करते${!var} हुए अप्रत्यक्ष विस्तार , जो चर का नाम जिसका varऔर में है , का उपयोग करता है
  • namerefs माध्यम से बनाया जा करने की जरूरत है जो declarebuiltin (या kshसंगत पर्याय, typeset)। चर का संदर्भ declare -n ref=varबनाता refहै var

नामेरेफ़्स भी अनुक्रमण का समर्थन करते हैं, इसमें यदि हमारे पास है arr=(a b c); declare -n ref=arr;तो ${ref[1]}विस्तार करेगा b। उपयोग ${!p[1]}करने के बजाय pएक सरणी के रूप में ले जाएगा , और इसके दूसरे तत्व द्वारा नामित चर को देखें।

बैश में, नामरेफ़्स का शाब्दिक अर्थ है कि, नाम से संदर्भ , और एक फ़ंक्शन के अंदर से नामांक का उपयोग करके नामित चर के स्थानीय मूल्य का उपयोग किया जाएगा। यह छपेगा local value of var

#!/bin/bash
fun() {
        local var="local value of var"
        echo "$ref";
}
var="global var"
declare -n ref=var
fun

BashFAQ का अप्रत्यक्ष पर एक लंबा लेख है , भी।


2
उच्च स्तरीय भाषाओं में अप्रत्यक्ष रूप से काफी उपयोगी है। उदाहरण perl में। वे सी पॉइंटर्स के समान नहीं हैं, लेकिन वे एक ही मूल कार्य करते हैं। यहां तक ​​कि बैश अप्रत्यक्ष रूप से चर का उपयोग कर सकते हैं ... लेकिन IMO यदि आप कोड लिखना शुरू कर देते हैं जो कि सुविधा का महत्वपूर्ण उपयोग करता है, तो आप पर्ल या कुछ के साथ खरोंच से शुरू करना बेहतर समझते हैं। Mywiki.wooledge.org/BashFAQ/006
cas

2
@ कै, ओह, बिल्कुल। लेकिन शायद उनके लिए मेमोरी पतों के बजाय वस्तुओं की ओर इशारा करना बेहतर होगा । (सी में भी, इसमें एक प्रकार शामिल है।) मेरा मतलब अप्रत्यक्ष विस्तार और नामरूप दोनों को नोट करना था, लेकिन तुरंत करने का समय नहीं था।
लक्काचु

यह संभवतः यह इंगित करने के लायक है कि फ़ोर-लूप उदाहरण अधिक स्वाभाविक रूप से लिखा गया है for foo in "${array[@]}" ; do ... doneजब तक कि आपको अन्य उद्देश्य (नों) के लिए सूचकांक की आवश्यकता न हो।
विल क्रॉफर्ड

@WillCrawford, बिंदु। उदाहरण संपादित किया और नोट किया।
ilkachachu

9

नहीं, bash"पॉइंटर्स" नहीं है, लेकिन इसमें संदर्भ हैं:

$ spam="fred"
$ declare -n tripe=spam
$ echo $tripe
fred
$ tripe=juki
$ echo $spam
juki

से bashआदमी पेज:

एक वेरिएबल को nameref एट्रिब्यूट का उपयोग करके declareया localबिल्टइन कमांड्स का उपयोग करके nameref, या दूसरे वेरिएबल के लिए रेफरेंस दिया जा सकता है। यह चर को अप्रत्यक्ष रूप से हेरफेर करने की अनुमति देता है। जब भी nameref वैरिएबल को संदर्भित किया जाता है, को असाइन किया जाता है, unset होता है, या इसकी विशेषताओं को संशोधित किया जाता है (nameref विशेषता का उपयोग करने या बदलने के अलावा), ऑपरेशन वास्तव में nameref वैरिएबल के मान द्वारा निर्दिष्ट चर पर किया जाता है। एक प्रकार का नाम आम तौर पर शेल फ़ंक्शंस के लिए उपयोग किया जाता है जिसका उल्लेख एक चर के लिए किया जाता है जिसका नाम फ़ंक्शन के तर्क के रूप में पारित किया जाता है। उदाहरण के लिए, यदि चर नाम को इसके पहले तर्क के रूप में शेल फ़ंक्शन में पास किया जाता है, तो चल रहा है

declare -n ref=$1

फ़ंक्शन के अंदर एक nameref वैरिएबल रेफरी बनाता है जिसका वैल्यू वैरिएबल नेम है जिसे पहले तर्क के रूप में पास किया गया है। संदर्भ और असाइनमेंट रेफरी करने के लिए, और इसकी विशेषताओं में परिवर्तन, संदर्भ, असाइनमेंट और विशेषता संशोधनों के रूप में व्यवहार किया जाता है, जिसका नाम $ 1 के रूप में पारित किया गया था। यदि लूप के लिए नियंत्रण चर में नामांक विशेषता होती है, तो शब्दों की सूची शेल चरों की सूची हो सकती है, और सूची में प्रत्येक शब्द के लिए एक नाम संदर्भ स्थापित किया जाएगा, बदले में, जब लूप निष्पादित किया जाता है। ऐरे वेरिएबल्स को nameref विशेषता नहीं दी जा सकती है। हालाँकि, nameref वैरिएबल एरे वेरिएबल्स और सबस्क्रिप्टेड ऐरे वेरिएबल्स को रेफर कर सकते हैं। नामरेफ़्स बिलिन में एन विकल्प का उपयोग करके परेशान हो सकते हैं unset। अन्यथा, यदिunset एक nameref चर के नाम के साथ निष्पादित किया जाता है एक तर्क के रूप में, nameref चर द्वारा संदर्भित चर परेशान होगा।


4

नहीं, शेल "पॉइंटर्स" का उपयोग नहीं करते हैं (जैसा कि सी में समझा गया है)।

ऐरे सूचकांक का उपयोग कर सकते हैं: echo "${array[2]}"लेकिन @आपके उदाहरण में वास्तव में एक "पॉइंटर" नहीं है। यह "सरणी मानों की सूची" को व्यक्त करने का एक तरीका है। शेल पार्सर को समझने के लिए कुछ। रास्ते के समान:

$ echo "$@"

सभी "स्थितिगत पैरामीटर" सूची में फैलता है।


2

हालांकि बैश पूर्णांक अनुक्रमित सरणियों को परिभाषित किया जा सकता है और इसे उसी तरह से एक्सेस किया जा सकता है;

declare -a obj
obj+=("val1")
obj+=("val2")

for item in ${obj[@]}; do
  echo "${obj[${item}]} ${item}"
done

बैश में साहचर्य या स्ट्रिंग आधारित अनुक्रमित सरणियों को निम्नलिखित पुनरावृत्त परिभाषा की आवश्यकता होती है;

declare -A obj
obj["key1"]="val1"
obj["key2"]="val2"

for item in ${!obj[@]}; do
  echo "${obj[${item}]} ${item}"
done

पॉइंटर्स के संबंध में प्रश्न का उत्तर देने और बैश से एक का उपयोग करने के लिए; संकलित बैश द्विआधारी के आंतरिक कार्यक्षमता वास्तव में स्मृति की ओर इशारा ढेर पर आवंटित का इस्तेमाल करते हैं करता है और के उपयोग के साथ इसी तरह की सुविधा का पर्दाफाश करता है eval। देखें [अप्रत्यक्ष संदर्भ] http://tldp.org/LDP/abs/html/ivr.html )

ड्रेगन हो; के उपयोग evalसुरक्षा के प्रभाव की वजह से सावधानी से किया जाना चाहिए

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