क्या स्थानीय चर असाइनमेंट के लिए उद्धरण आवश्यक हैं?


36

क्या मैं स्थानीय असाइनमेंट के दाईं ओर उद्धरण सुरक्षित रूप से छोड़ सकता हूं?

function foo {
    local myvar=${bar}
    stuff()
}

मुझे मुख्य रूप से दिलचस्पी है bash, लेकिन अन्य गोले में कोने के मामलों में किसी भी जानकारी का स्वागत है।


मुझे लगता है कि इससे कोई फर्क नहीं पड़ता अगर यह एक पंक्ति में है जैसे कि आपके कार्य में है। असाइनमेंट को उद्धृत करने की आवश्यकता नहीं है। Mpi-sb.mpg.de/departments/rg1/teaching/unixffb-ss98/…
jirib

जवाबों:


41

उद्धरण में की जरूरत है export foo="$var"या local foo="$var"(या readonly, typeset, declareऔर अन्य चर घोषित करने आदेशों ) में:

  • dash
  • shNetBSD की (भी Almquist खोल के आधार पर)।
  • shFreeBSD 9.2 या उससे अधिक है (देखें 9.3 में परिवर्तन )
  • yash
  • zsh5.1 kshया shएमुलेशन से पहले के संस्करणों के साथ (या export var="$(cmd)"जहाँ पर zshशब्द विभाजन करना होगा अन्यथा ग्लोबिंग नहीं)।

जैसा कि अन्यथा चर विस्तार शब्द विभाजन और / या फ़ाइल नाम पीढ़ी के अधीन होगा जैसे किसी भी तर्क में किसी अन्य कमांड के लिए।

और इसमें आवश्यक नहीं हैं:

  • bash
  • ksh (सभी कार्यान्वयन)
  • shFreeBSD 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

मेरी सलाह हमेशा बोली होगी।


3
ध्यान दें कि में zshउद्धरण कर रहे हैं के लिए आवश्यक local foo="$(cmd)"है क्योंकि wordsplitting (लेकिन फ़ाइल नाम पीढ़ी) है (लेकिन गैर उद्धृत पैरामीटर विस्तार के लिए नहीं) गैर उद्धृत आदेश प्रतिस्थापन के लिए प्रदर्शन किया, जब तक कि KSH_TYPESETसक्षम किया गया है, जिसमें मामले उद्धरण नहीं कर रहे हैं की जरूरत है। सही बात? नहीं? तब तक हमेशा सब कुछ बोली जब तक आपको पता नहीं है कि आप क्या कर रहे हैं।
मैट

2
@ मैट, मुझे आपका निष्कर्ष अच्छा लगा। : D यह मज़ेदार है, मैंने शेल स्क्रिप्टिंग के बारे में जो कुछ भी सीखा है, वह इस स्टेक्सएक्सचेंज से आया है, ताकि मुझे महसूस न हो कि हमेशा आपके चर को उद्धृत करना स्क्रिप्ट लेखकों के बीच सामान्य ज्ञान नहीं है । मुझे लग रहा है कि मेरे पास मौजूदा प्रोडक्शन स्क्रिप्ट्स को करने के लिए बहुत से फिक्सिंग हैं, जो लोगों द्वारा लिखित नहीं हैं, और बिल्कुल नहीं जानते कि वे क्या कर रहे थे ....
Wildcard

3

मैं आमतौर पर चर के किसी भी उपयोग को उद्धृत करता हूं जहां सफेद रिक्त स्थान जैसे वर्ण हो सकते हैं। अन्यथा आप इस तरह की समस्याओं में भाग लेंगे:

#!/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जब हम इसका उपयोग करने गए थे।


2
शब्द बंटवारे गैर उद्धृत चर के साथ ही समस्या नहीं है, तो आप पर विचार करने के लिए फ़ाइल नाम पीढ़ी (उर्फ ग्लोबिंग) के रूप में अच्छी तरह से (हालांकि कि (दोनों) अलग-अलग कार्य में और के लिए लागू नहीं होता है bashऔर kshमें local/ typeset... विशेष builtins)।
स्टीफन चेज़लस
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.