शेल में $ @ की डेटा संरचना क्या है?


13

हम आमतौर पर $@$ 0 को छोड़कर सभी तर्क का प्रतिनिधित्व करते हैं। हालाँकि, मुझे नहीं पता कि डेटा संरचना क्या $@है।

$*जब दोहरे उद्धरण चिह्नों में शामिल होने के साथ यह अलग व्यवहार करता है , तो क्या कोई मुझे दुभाषिया स्तर की व्याख्या दे सकता है?

यह लूप के लिए पुनरावृत्त हो सकता है, इसलिए यह सरणी प्रतीत होता है। हालांकि, यह पूरी तरह से सरल के साथ भी प्रतिध्वनित हो सकता है echo $@, अगर यह एक सरणी है, तो केवल पहला तत्व दिखाया जाएगा। शेल की सीमा के कारण, मैं इसे बाहर ले जाने के लिए अधिक प्रयोग कोड नहीं लिख सकता।

इस पोस्ट के बीच अंतर : यह पोस्ट दिखाती है कि किस $@तरह से अलग व्यवहार किया जाता है $*। लेकिन मैं डेटा प्रकार के बारे में सोच रहा हूं $@। पाइथन की तरह व्याख्या करने वाली भाषा के रूप में शेल को मौलिक प्रकारों की एक श्रृंखला के अनुसार डेटा का प्रतिनिधित्व करना चाहिए। या दूसरे शब्दों में, मैं जानना चाहता हूं कि $ @ को कंप्यूटर मेमोरी में कैसे संग्रहीत किया जाता है।

क्या यह एक स्ट्रिंग, एक बहु-पंक्ति स्ट्रिंग या एक सरणी है?

यदि यह एक अद्वितीय डेटा प्रकार है, तो क्या इस प्रकार के उदाहरण के रूप में कस्टम चर को परिभाषित करना संभव है?



@ हेक्सियल, मुझे ऐसा नहीं लगता, मैंने अपनी पोस्ट के नीचे उनका अंतर लिखा है।
davmos

बेहतर होगा कि आप आउटपुट में अंतर को परखें printf '%s\n' "$@"और printf '%s\n' "$*"echoउपयोगिता सिर्फ अपने तर्कों, कोई फर्क नहीं पड़ता आउटपुट अगर वे एक या कई हैं। दोनों एरेज़ (स्ट्रिंग्स के) हैं, लेकिन डबल उद्धृत होने पर वे अलग तरह से व्यवहार करते हैं। यदि या तो एक मल्टी-लाइन स्ट्रिंग था, तो वे मल्टी-लाइन स्ट्रिंग्स (जो वे कर सकते हैं) को स्टोर करने में सक्षम नहीं होंगे। यह स्पष्ट नहीं है कि आप किस मुद्दे को हल करने की कोशिश कर रहे हैं।
Kusalananda

2
आपका प्रश्न यह पूछने के बराबर है कि @varपर्ल एक अंतर्निहित भंडारण के संदर्भ में क्या है । एक साधारण पर्ल कार्यक्रम के दृष्टिकोण से, यह वास्तव में मायने नहीं रखता है, इसके अलावा यह एक सरणी / सूची के रूप में सुलभ है (और तथ्य यह है कि ऐसे संदर्भ हैं जिसमें एक सूची अपेक्षित है)।
Kusalananda

जवाबों:


16

कि बॉर्न खोल में एक हैक के रूप में शुरू किया। बॉर्न शेल में, IFS शब्द विभाजन सूची के संदर्भ में सभी शब्दों पर (टोकन के बाद) किया गया था (कमांड लाइन तर्क या शब्द forलूप लूप पर)। अगर आप के पास था:

IFS=i var=file2.txt
edit file.txt $var

दूसरी पंक्ति 3 शब्दों में tokenised किया जाएगा यही कारण है, $varका विस्तार किया जा सकता है, और विभाजन + ग्लोब तीनों शब्द पर किया जाना होगा, इसलिए आपके द्वारा चलाए जा खत्म होगा edसाथ t, f, le.txt, f, le2.txtतर्क के रूप में।

उस के भाग को उद्धृत करने से विभाजन + ग्लोब रोका जा सकेगा। बॉर्न शेल को शुरू में याद था कि आंतरिक रूप से उन पर 8 बिट को सेट करके कौन से वर्ण उद्धृत किए गए थे (जो बाद में बदलकर यूनिक्स 8 बिट साफ हो गया, लेकिन शेल अभी भी कुछ ऐसा ही याद रखने के लिए किया गया था जिसे बाइट उद्धृत किया गया था)।

दोनों $*और $@अंतरिक्ष के बीच के साथ स्थितीय मापदंडों के संयोजन थे। लेकिन $@दोहरे उद्धरण चिह्नों के अंदर एक विशेष प्रसंस्करण था । यदि $1निहित foo barऔर $2निहित है baz, "$@"तो इसका विस्तार होगा:

foo bar baz
^^^^^^^ ^^^

( ^उपरोक्त वर्णों में से कौन सा वर्ण 8 वें बिट सेट है)। जहां पहले स्थान को उद्धृत किया गया था (8 वां बिट सेट था) लेकिन दूसरा नहीं (एक जोड़ा गया-इन-बीच शब्द)।

और यह IFS विभाजन है जो तर्कों को अलग करने का ख्याल रखता है (यह मानकर कि अंतरिक्ष वर्ण $IFSडिफ़ॉल्ट रूप से है)। यह $*अपने पूर्ववर्ती माशी शेल (थॉमसन शेल पर आधारित है, जबकि बॉर्न शेल खरोंच से लिखा गया था) में इसका विस्तार कैसे किया गया था, इसके समान है ।

यह बताता है कि बॉर्न शेल में शुरू "$@"में खाली स्ट्रिंग का विस्तार क्यों होगा, इसके बजाय कुछ भी नहीं होने पर स्थितिगत मापदंडों की सूची खाली थी (आपको इसके साथ काम करना ${1+"$@"}पड़ता था), यह खाली स्थितीय मापदंडों को क्यों नहीं रखता था और क्यों "$@"नहीं किया था जब $IFSअंतरिक्ष वर्ण नहीं था तो काम नहीं करेगा।

इरादा एक अन्य आदेश के लिए तर्कों की सूची को पारित करने में सक्षम होना था, लेकिन यह खाली सूची के लिए ठीक से काम नहीं करता था, खाली तत्वों के लिए या जब $IFSअंतरिक्ष में नहीं था (पहले दो मुद्दे अंततः बाद के संस्करणों में तय किए गए थे )।

कोर्न शेल (जिस पर POSIX कल्पना आधारित है) ने उस व्यवहार को कुछ तरीकों से बदल दिया:

  • आईएफएस विभाजन केवल निर्विवाद विस्तार के परिणाम पर किया जाता है (न कि शाब्दिक शब्दों पर जैसे editया file.txtऊपर के उदाहरण में)
  • $*और रिक्त स्थान $@के पहले अक्षर के साथ जुड़ जाते हैं, $IFSजब $IFSकिसी को उद्धृत करने के अलावा खाली होता है "$@", तो उस जॉइनर को बॉर्न शेल की तरह अनक्वॉटेड किया जाता है और खाली "$*"होने पर उद्धृत IFSकिए जाने पर, सेपरेटर के बिना स्थितीय मापदंडों को जोड़ दिया जाता है।
  • यह सरणियों के लिए समर्थन जोड़ा, और साथ ${array[@]} ${array[*]}बॉर्न की याद ताजा करती $*है और $@लेकिन 1 के बजाय indice 0 से शुरू, और विरल (साहचर्य सरणियों की तरह अधिक), जो साधन $@वास्तव में एक ksh सरणी के रूप में नहीं माना जा सकता (के साथ तुलना csh/ rc/ zsh/ fish/ yashजहां $argv/ $*सामान्य हैं सरणियों)।
  • खाली तत्वों को संरक्षित किया जाता है।
  • "$@"जब $#0 होता है अब खाली स्ट्रिंग के बजाय कुछ भी नहीं फैलता है, "$@"तब काम करता है जब खाली $IFSहोने के अलावा रिक्त स्थान नहीं होते हैं IFS$*वाइल्डकार्ड के बिना निर्विवाद एक तर्क (जहां स्थितीय पैरामीटर अंतरिक्ष के साथ जुड़ जाते हैं) के $IFSखाली होने पर फैलता है।

ksh93 ने शेष कुछ समस्याओं को ठीक किया। Ksh93 में, $*और $@स्थिति के मापदंडों की सूची में विस्तार होता है, की कीमत की परवाह किए बिना अलग हो जाता है $IFS, और फिर सूची संदर्भों में आगे विभाजित + ग्लोबेड + ब्रेस-विस्तारित, सूची $*के पहले बाइट (चरित्र) के साथ शामिल हो जाता है $IFS, "$@"सूची के संदर्भ में सूची में फैलता है की स्थिति की परवाह किए बिना, मानदंड के मानदंड $IFS। गैर सूची संदर्भ में, में की तरह var=$@, $@अंतरिक्ष के साथ परवाह किए बिना के मूल्य के शामिल हो गए है $IFS

bashके सरणियों ksh वाले के बाद डिजाइन किए हैं। अंतर हैं:

  • निर्विवाद विस्तार पर कोई ब्रेस-विस्तार नहीं
  • $IFSबाइट के लिए के बजाय पहले चरित्र
  • खाली $*होने पर गैर-सूची के संदर्भ में गैर-उद्धृत किए जाने के विस्तार की तरह कुछ कोने के मामले में अंतर $IFS

जबकि POSIX कल्पना बहुत अस्पष्ट हुआ करती थी, अब यह कमोबेश बैश व्यवहार को निर्दिष्ट करती है।

यह उस में kshया सामान्य सरणियों से अलग bashहै:

  • इंडेक्स 0 के बजाय 1 पर शुरू होता है ( "${@:0}"जिसमें $0( जिसमें एक पोजीशनर पैरामीटर नहीं है, और कार्यों में आपको फ़ंक्शन का नाम दिया गया है या नहीं, यह शेल के आधार पर होता है और फ़ंक्शन कैसे परिभाषित किया गया था)।
  • आप व्यक्तिगत रूप से तत्व असाइन नहीं कर सकते हैं
  • यह विरल नहीं है, आप व्यक्तिगत रूप से तत्वों को परेशान नहीं कर सकते
  • shift इस्तेमाल किया जा सकता है।

में zshया yashजहां सरणियों सामान्य सरणियों हैं (विरल नहीं, सूचकांक एक पर अन्य सभी के गोले लेकिन ksh / बैश में की तरह शुरू), $*एक सामान्य सरणी के रूप में व्यवहार किया जाता है। zshइसके $argvलिए एक उपनाम के रूप में (साथ संगतता के लिए csh) है। $*के रूप में ही है $argvया ${argv[*]}(तर्क पहले संदर्भ के साथ शामिल हो गए, $IFSलेकिन अभी भी सूची संदर्भों में अलग हो गए हैं)। कोर्न-शैली विशेष प्रसंस्करण की "$@"तरह "${argv[@]}"या उससे "${*[@]}"}गुजरती है।


8

हालाँकि, मुझे नहीं पता कि डेटा संरचना क्या $@है।

यह एक विशेष पैरामीटर है जो स्थितिगत मापदंडों के मूल्यों तक फैलता है ... लेकिन यह शब्दावली के बारे में स्पष्ट है।

हम के कुछ हिस्सों के रूप में स्थितीय मापदंडों देख सकते हैं $@तो यह विशिष्ट तत्वों की एक संख्या है, ( $1, $2...), कि स्वतंत्र रूप से पहुँचा जा सकता है और लगातार प्राकृतिक संख्या द्वारा नामित कर रहे हैं। यह कुछ ऐसा बनाता है जिसे आमतौर पर एक सरणी कहा जाता है।

वाक्य-विन्यास थोड़ा अजीब है, हालांकि, और यहां तक ​​कि सीमित भी है। व्यक्तिगत रूप से सरणी के किसी एक तत्व को संशोधित करने का कोई तरीका नहीं है। इसके बजाय, एक ही बार में पूरी चीज़ सेट करनी होगी। (आप set -- "$@" fooकिसी मूल्य set -- "${@:1:2}" foo "${@:3}"को जोड़ने के लिए , या बीच में एक मूल्य जोड़ने के लिए उपयोग कर सकते हैं । लेकिन आप दोनों मामलों में आपको पूरी परिणामी सूची लिखनी होगी।)

$*जब यह दोहरे भाव में शामिल होने के साथ अलग व्यवहार करता है ,

क्योंकि वे अलग तरह से व्यवहार करने के लिए परिभाषित हैं।

हालांकि, यह पूरी तरह से सरल के साथ भी प्रतिध्वनित हो सकता है echo $@, अगर यह एक सरणी है, तो केवल पहला तत्व दिखाया जाएगा।

यदि आप इस तथ्य का मतलब है कि a=(foo bar asdf); echo $aबस उत्पादन होगा foo, तो यह ज्यादातर खोल वाक्यविन्यास का एक हिस्सा है, और तथ्य यह है कि ksh- शैली नामित सरणियों बाद में स्थितीय मापदंडों और की तुलना में बनाया गया था $@। सादा $aसमान है, ${a[0]}इसलिए इसका एकल स्केलर मान का पिछड़ा-संगत अर्थ है, भले ही aएक सरणी या एक साधारण स्केलर चर हो।

@संकेत पूरी सूची की चर्चा करते हुए कि में नाम सरणियों के साथ पुन: उपयोग किया गया था "${a[@]}"जिस तरह से पूरी सूची पाने के लिए है। नामांकित सरणियों की तुलना में $@, अनावश्यक ब्रेसिज़ और कोष्ठक और नाम को छोड़ दिया जाता है।

या दूसरे शब्दों में, मैं जानना चाहता हूं कि $@कंप्यूटर मेमोरी में कैसे संग्रहीत किया जाता है।

यह कार्यान्वयन पर निर्भर करता है, आपको किसी विशेष शेल के स्रोत कोड को देखना होगा जिसकी आपको परवाह है।

क्या यह एक स्ट्रिंग, एक बहु-पंक्ति स्ट्रिंग या एक सरणी है?

एक सरणी, ज्यादातर। हालांकि, ऐश नाम की ksh- शैली से अलग, क्योंकि वे अनुक्रमणिका के रूप में मनमाने ढंग से nonnegative पूर्णांक हो सकते हैं, न कि केवल लगातार के साथ $@। (अर्थात्, एक नामित सरणी विरल हो सकती है, और उदाहरण के लिए अनुक्रमणिकाएं हैं 1, 3और 4, साथ 0और 2गायब है। यह स्थितिगत मापदंडों के साथ संभव नहीं है।)

यह एक एकल स्ट्रिंग नहीं है, क्योंकि इसे अलग-अलग तत्वों तक विस्तारित किया जा सकता है, और तत्वों की रेखाओं को कॉल करना भी सही नहीं है, क्योंकि किसी भी नियमित चर, या स्थितिगत मापदंडों (तत्वों $@) में से एक में भी नया अंक हो सकता है।

यदि यह एक अद्वितीय डेटा प्रकार है, तो क्या इस प्रकार के उदाहरण के रूप में कस्टम चर को परिभाषित करना संभव है?

नहीं, लेकिन नामांकित सरणियाँ संभवतः वैसे भी अधिक उपयोगी हैं।


1
+1। TL: DR $@एक डेटा संरचना नहीं है, यह स्थिति-मापदंडों डेटा संरचना के विस्तार के लिए कुछ कार्यों / ऑपरेटरों में से एक है ।
पीटर कॉर्ड्स
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.