क्या मैं स्थानीय असाइनमेंट के दाईं ओर उद्धरण सुरक्षित रूप से छोड़ सकता हूं?
function foo {
local myvar=${bar}
stuff()
}
मुझे मुख्य रूप से दिलचस्पी है bash, लेकिन अन्य गोले में कोने के मामलों में किसी भी जानकारी का स्वागत है।
क्या मैं स्थानीय असाइनमेंट के दाईं ओर उद्धरण सुरक्षित रूप से छोड़ सकता हूं?
function foo {
local myvar=${bar}
stuff()
}
मुझे मुख्य रूप से दिलचस्पी है bash, लेकिन अन्य गोले में कोने के मामलों में किसी भी जानकारी का स्वागत है।
जवाबों:
उद्धरण में की जरूरत है export foo="$var"या local foo="$var"(या readonly, typeset, declareऔर अन्य चर घोषित करने आदेशों ) में:
dashshNetBSD की (भी Almquist खोल के आधार पर)।shFreeBSD 9.2 या उससे अधिक है (देखें 9.3 में परिवर्तन )yashzsh5.1 kshया shएमुलेशन से पहले के संस्करणों के साथ (या export var="$(cmd)"जहाँ पर zshशब्द विभाजन करना होगा अन्यथा ग्लोबिंग नहीं)।जैसा कि अन्यथा चर विस्तार शब्द विभाजन और / या फ़ाइल नाम पीढ़ी के अधीन होगा जैसे किसी भी तर्क में किसी अन्य कमांड के लिए।
और इसमें आवश्यक नहीं हैं:
bashksh (सभी कार्यान्वयन)shFreeBSD 9.3 या नए कीsh(2005 से)zshzshजब तक shया kshउत्सर्जन में , विभाजन + ग्लोब को पैरामीटर विस्तार पर कभी नहीं किया जाता है , लेकिन कमांड प्रतिस्थापन पर विभाजन (ग्लोब नहीं) किया जाता है। चूंकि संस्करण 5.1, export/ localऔर अन्य डिक्लेरेशन कमांड दोहरे कीवर्ड / बिलियन कमांड्स बन गए हैं , जैसे ऊपर दिए गए अन्य गोले, जिसका अर्थ है कि उद्धरण आवश्यक नहीं है, यहां तक कि sh/ kshएमुलेशन और यहां तक कि कमांड प्रतिस्थापन के लिए भी।
विशेष मामले हैं जहां उद्धृत करना उन गोले में भी आवश्यक है, जैसे:
a="b=some value"
export "$a"
या अधिक आम तौर पर, अगर कुछ भी छोड़ दिया =(सहित =) उद्धृत है या कुछ विस्तार का परिणाम है (जैसे export 'foo'="$var", export foo\="$var"या export foo$((n+=1))="$var"(जिसे $((...))वास्तव में भी उद्धृत किया जाना चाहिए) ...)। या दूसरे शब्दों में जब तर्क exportमान्य वैरिएबल असाइनमेंट नहीं हो सकता है अगर बिना लिखा हो export।
यदि export/ localआदेश नाम ही उद्धृत किया गया है (यहां तक कि जैसे भाग में "export" a="$b", 'ex'port a="$b", \export a="$b", या यहाँ तक ""export a="$b"), चारों ओर उद्धरण $bएटी एंड टी को छोड़कर की जरूरत है kshऔर mksh।
यदि export/ localया इसका कुछ हिस्सा कुछ विस्तार (जैसे cmd=export; "$cmd" a="$b"या यहां तक कि export$(:) a="$b") या जैसी चीजों का परिणाम है dryrun=; $dryrun export a="$b", तो उद्धरण प्रत्येक शेल में आवश्यक हैं।
के मामले में > /dev/null export a="$b", उद्धरण की आवश्यकता है pdkshऔर इसके कुछ व्युत्पन्न हैं।
के लिए command export a="$b", उद्धरण हर खोल लेकिन में की जरूरत है mkshऔर ksh93(के बारे में एक ही कैविएट्स के साथ commandऔर exportनहीं कुछ विस्तार का परिणाम रहा है)।
लिखित होने पर उन्हें किसी भी शेल में जरूरत नहीं है:
foo=$var export foo
(यह वाक्यविन्यास बॉर्न शेल के साथ भी संगत है, लेकिन हाल के संस्करणों में zsh, केवल जब sh/ kshअनुकरण में काम कर रहा है )।
(ध्यान दें कि var=value local varप्रयोग नहीं किया जाना चाहिए क्योंकि व्यवहार गोले में भिन्न होता है)।
यह भी ध्यान रखें कि का उपयोग कर exportएक काम के साथ भी मतलब है कि के निकास स्थिति cmdमें export var="$(cmd)"खो दिया है। यह export var; var=$(cmd)समस्या के रूप में नहीं है।
इस विशेष मामले से भी सावधान रहें bash:
$ bash -c 'IFS=; export a="$*"; echo "$a"' bash a b
ab
$ bash -c 'IFS=; export a=$*; echo "$a"' bash a b
a b
मेरी सलाह हमेशा बोली होगी।
zshउद्धरण कर रहे हैं के लिए आवश्यक local foo="$(cmd)"है क्योंकि wordsplitting (लेकिन फ़ाइल नाम पीढ़ी) है (लेकिन गैर उद्धृत पैरामीटर विस्तार के लिए नहीं) गैर उद्धृत आदेश प्रतिस्थापन के लिए प्रदर्शन किया, जब तक कि KSH_TYPESETसक्षम किया गया है, जिसमें मामले उद्धरण नहीं कर रहे हैं की जरूरत है। सही बात? नहीं? तब तक हमेशा सब कुछ बोली जब तक आपको पता नहीं है कि आप क्या कर रहे हैं।
मैं आमतौर पर चर के किसी भी उपयोग को उद्धृत करता हूं जहां सफेद रिक्त स्थान जैसे वर्ण हो सकते हैं। अन्यथा आप इस तरह की समस्याओं में भाग लेंगे:
#!/bin/bash
bar="hi bye"
function foo {
local myvar=${bar}
printf "%s\n" $myvar
printf "%s\n" "$myvar"
}
foo
एक असाइनमेंट में वैरिएबल का उपयोग उद्धरणों की आवश्यकता के लिए नहीं होता है, लेकिन जब आप इसका उपयोग करने के लिए जाते हैं जैसे कि printfआपको वहां इसकी आवश्यकता होगी:
printf "%s\n" "$myvar"
नोट: याद रखें कि चर $IFSवह है जो विभाजक वर्णों को नियंत्रित करता है।
IFS The Internal Field Separator that is used for word splitting after
expansion and to split lines into words with the read builtin command.
The default value is ``<space><tab><newline>''.
बैश में सक्षम डिबगिंग के साथ हम देख सकते हैं कि पर्दे के पीछे क्या हो रहा है।
$ bash -x cmd.bash
+ bar='hi bye'
+ foo
+ local 'myvar=hi bye'
+ printf '%s\n' hi bye
hi
bye
+ printf '%s\n' 'hi bye'
hi bye
उपर्युक्त में हम देख सकते हैं कि चर $barको ठीक कर दिया गया था , $myvarलेकिन तब जब हम उपयोग करने के लिए गए तो हमें उस $myvarसामग्री का संज्ञान होना चाहिए $myvarजब हम इसका उपयोग करने गए थे।
bashऔर kshमें local/ typeset... विशेष builtins)।