कमांड पर bash स्क्रिप्ट का अस्थायी मान


11

कमांड की तरह,

if true; then
   IFS=":" read a b c d e f <<< "$test"

पुस्तक कहती है जब IFS ":"मुख्य कमांड ( read a b c d e f <<< "$value") से पहले मान असाइनमेंट कमांड ( ) का उपयोग किया जाता है , तो इसका मान अस्थायी रूप से मुख्य कमांड पर प्रभावी होता है। तो, readकमांड सीमांकक का उपयोग करता है :

लेकिन, इस कमांड की तरह,

if true; then
   HOME="hello" echo "$HOME"

इको मैसेज हैलो नहीं है। उपरोक्त आदेश का वास्तविक अर्थ क्या है?

जवाबों:


5

यह इस सवाल पर आता है कि मूल्यांकन कैसे काम करता है। दोनों उदाहरण एक ही तरीके से काम करते हैं, समस्या यह होती है कि शेल (बैश, यहां) चर का विस्तार कैसे करता है।

जब आप यह कमांड लिखते हैं:

HOME="foo" echo $HOME

$HOMEविस्तार किया जाता है से पहले आदेश चला जाता है । इसलिए, इसे मूल मान में विस्तारित किया जाता है न कि नए को जिसे आपने कमांड के लिए सेट किया है। HOMEचर वास्तव में वातावरण है कि में बदल दिया गया है echoआदेश में चल रहा है, हालांकि, आप प्रिंट कर रहे हैं $HOMEमाता पिता से।

वर्णन करने के लिए, इस पर विचार करें:

$ HOME="foo" bash -c 'echo $HOME'
foo
$ echo $HOME
/home/terdon

जैसा कि आप ऊपर देख सकते हैं, पहला कमांड अस्थायी रूप से परिवर्तित मूल्य को HOMEप्रिंट करता है और दूसरा यह दर्शाता है कि चर केवल अस्थायी रूप से बदला गया था। क्योंकि bash -c ...कमांड ' 'डबल कोट्स ( ) के बजाय सिंगल कोट्स ( ) में संलग्न है " ", वेरिएबल का विस्तार नहीं है और इसे नए बैश प्रोसेस के रूप में पास किया गया है। यह नई प्रक्रिया फिर इसे विस्तारित करती है और इसे निर्धारित किए गए नए मूल्य को प्रिंट करती है। यदि आप उपयोग करते हैं तो आप इसे देख सकते हैं set -x:

$ set -x
$ HOME="hello" echo "$HOME"
+ HOME=hello         
+ echo hello
hello

जैसा कि आप ऊपर देख सकते हैं, चर $HOME को कभी भी पारित नहीं किया गया है echo। यह केवल इसका विस्तारित मूल्य देखता है। तुलना करना:

$ HOME="hello" bash -c 'echo $HOME'
+ HOME=hello
+ bash -c 'echo $HOME'
hello

यहां, एकल उद्धरणों के कारण, चर और इसके मूल्य को नई प्रक्रिया में पारित नहीं किया गया है।


7

जब शेल एक लाइन को पार्स कर रहा होता है, तो यह लाइन को शब्दों में बदल देगा, शब्दों पर विभिन्न विस्तार (क्रम में) करेगा, फिर कमांड निष्पादित करेगा।

मान लीजिए test=1:2:3:4:5:6

आइए इस कमांड को देखें: IFS=":" read a b c d e f <<< "$test"

टोकनिंग के बाद, और पैरामीटर विस्तार होता है:IFS=":" read a b c d e f <<< "1:2:3:4:5:6"

शेल रीड कमांड की अवधि के लिए IFS वेरिएबल सेट करेगा, और readइसके इनपुट में $ IFS को लागू करने का तरीका जानता है , और वैरिएबल नामों को मान देता है।

इस आदेश में एक समान कहानी है, लेकिन अलग परिणाम: HOME="hello" echo "$HOME"

चूंकि कमांड शुरू होने से पहले पैरामीटर का विस्तार होता है, शेल में है:

HOME="hello" echo "/home/username"

और फिर, इको कमांड के निष्पादन के दौरान, $ HOME के ​​नए मूल्य का उपयोग बिल्कुल नहीं किया जाता है।

आप जो करने की कोशिश कर रहे हैं उसे प्राप्त करने के लिए, इनमें से एक चुनें

# Delay expansion of the variable until its new value is set
HOME="hello" eval 'echo "$HOME"'

या

# Using a subshell, so the altered env variable does not affect the parent.
# The semicolon means that the variable assignment will occur before
# the variable expansion
(HOME="hello"; echo "$HOME")

लेकिन पहले वाले को मत उठाओ।


पहले वाले को चुनना शायद बेहतर होगा। कम से कम यह काफी तेज है। जब स्पष्ट उत्तर होता है, तो आप कभी-कभी गलत प्रश्न पूछ रहे हैं। लेकिन अगर किसी को कुछ कारणों से ऐसा करना चाहिए, तो जवाब बदलने से सवाल खुद ही कम गलत नहीं होगा। एक अन्य समाधान यह है कि इसे एक फ़ंक्शन में लपेटें और उपयोग करें local
user23013

evalसमाधान से क्यों बचना चाहिए?
DarkHeart

यदि आप इनपुट को सख्ती से नियंत्रित नहीं करते हैं, तो आपको उस कोड के बारे में बहुत सावधान रहना होगा जिसे आप अन्य लोगों को अपने प्रोग्राम में इंजेक्ट करने की अनुमति देते हैं।
ग्लेन जैकमैन

-1

दो स्कोप हैं: पर्यावरण चर और स्थानीय चर। वातावरण चर हर प्रक्रिया (देखें के लिए मान्य हैं setenv, getenvजबकि स्थानीय चर केवल इस खोल सत्र के भीतर सक्रिय हैं,)। (यह स्पष्ट अंतर नहीं है ...)

निहित env(आपके उदाहरण में) पर्यावरण को संशोधित करता है, जबकि echo ...स्थानीय लोगों का उपयोग करता है - इसलिए envइसका कोई प्रभाव नहीं है।

स्थानीय चर उपयोग को संशोधित करने के लिए, कहते हैं,

( HOME="foo" ; echo "$HOME" )

यहाँ कोष्ठक इस कार्य के दायरे को परिभाषित करते हैं।


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