क्या मैं स्थानीय असाइनमेंट के दाईं ओर उद्धरण सुरक्षित रूप से छोड़ सकता हूं?
function foo {
local myvar=${bar}
stuff()
}
मुझे मुख्य रूप से दिलचस्पी है bash
, लेकिन अन्य गोले में कोने के मामलों में किसी भी जानकारी का स्वागत है।
क्या मैं स्थानीय असाइनमेंट के दाईं ओर उद्धरण सुरक्षित रूप से छोड़ सकता हूं?
function foo {
local myvar=${bar}
stuff()
}
मुझे मुख्य रूप से दिलचस्पी है bash
, लेकिन अन्य गोले में कोने के मामलों में किसी भी जानकारी का स्वागत है।
जवाबों:
उद्धरण में की जरूरत है export foo="$var"
या local foo="$var"
(या readonly
, typeset
, declare
और अन्य चर घोषित करने आदेशों ) में:
dash
sh
NetBSD की (भी Almquist खोल के आधार पर)।sh
FreeBSD 9.2 या उससे अधिक है (देखें 9.3 में परिवर्तन )yash
zsh
5.1 ksh
या sh
एमुलेशन से पहले के संस्करणों के साथ (या export var="$(cmd)"
जहाँ पर zsh
शब्द विभाजन करना होगा अन्यथा ग्लोबिंग नहीं)।जैसा कि अन्यथा चर विस्तार शब्द विभाजन और / या फ़ाइल नाम पीढ़ी के अधीन होगा जैसे किसी भी तर्क में किसी अन्य कमांड के लिए।
और इसमें आवश्यक नहीं हैं:
bash
ksh
(सभी कार्यान्वयन)sh
FreeBSD 9.3 या नए कीsh
(2005 से)zsh
zsh
जब तक 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)।