"A = 10 इको $ A" 10 प्रिंट क्यों नहीं करता है?


25

यह आदेश:

A=10 echo $A

एक खाली लाइन प्रिंट करता है। क्यों नहीं 10? इन-प्लेस अस्थायी वातावरण सेटिंग काम क्यों नहीं करती है?

मैं समाधान के बजाय कारण और स्पष्टीकरण जानना चाहता हूं।

मैंनें इस्तेमाल किया

LANG=C gcc ...

सिस्टम भाषा (चीनी) के बजाय gcc की फ़ालबैक भाषा (अंग्रेज़ी) का उपयोग करने के लिए मजबूर करना। इसलिए मुझे लगता है कि एक VAR=valueउपसर्ग कमांड के लिए एक अस्थायी वातावरण का पालन करेगा। लेकिन ऐसा लग रहा है कि मुझे कुछ गलतफहमी है।

जवाबों:


22

यह उस आदेश का मामला है जिसमें किसी कमांड के मूल्यांकन के विभिन्न चरण होते हैं।

A=10 echo $Aपहले तीन शब्दों से बने एक साधारण कमांड में कमांड को पार्स करता है A=10, echoऔर $A। तब प्रत्येक शब्द परिवर्तनशील परिवर्तन से गुज़रता है, अर्थात परिवर्तनशील विस्तार जैसे कि $Aउनके मूल्य

यदि Aमान है fooशुरू में, विस्तार कदम के परिणाम एक साधारण आदेश अभी भी तीन शब्द है जो है: A=10, echoऔर foo। (शेल इस बिंदु पर भी याद करता है कि कौन से वर्ण शुरू में उद्धरण के भीतर थे - इस मामले में, कोई भी नहीं।) अगला कदम कमांड निष्पादित करना है। चूंकि A=10एक समान चिह्न के बाद एक मान्य चर नाम के साथ शुरू होता है, इसे एक असाइनमेंट के रूप में माना जाता है; चर Aको 10कमांड के निष्पादन के दौरान शेल और पर्यावरण दोनों में सेट किया जाता है। (आम तौर पर आप लिखने की जरूरत export Aहै करने के लिए Aतो यह एक कमांड नाम (यह एक अंतर्निहित आदेश) माना जाता है अगले शब्द एक काम नहीं है, है, यह एक अपवाद है वातावरण में और सिर्फ एक खोल चर के रूप में नहीं।)। echoकमांड किसी भी वैरिएबल पर निर्भर नहीं करता है, इसलिए A=10 echo $Aइसका ठीक वैसा ही असर होता है जैसा कि होता है echo $A

यदि आप केवल एक कमांड की अवधि के लिए एक चर सेट करना चाहते हैं, लेकिन कमांड को निष्पादित करते समय असाइनमेंट को ध्यान में रखते हुए, आप एक उप-संस्करण का उपयोग कर सकते हैं। कोष्ठक द्वारा दर्शाया गया एक सबशेल, सब स्टेट परिवर्तन (चर असाइनमेंट, करंट डाइरेक्टरी, फंक्शन डेफिनिशन, इत्यादि) को सबस्क्रिप्शन के लिए स्थानीय बनाता है।

(A=10; echo $A)

करें कि export A=10यदि आप इतना है कि यह बाहरी प्रोग्राम द्वारा देखा जाता है पर्यावरण के लिए चर निर्यात करना चाहते हैं।


धन्यवाद, क्या मैं कह सकता हूं A=10 (echo $A)और प्राप्त कर सकता हूं 10?
पृथ्वी इंजन

2
@EarthEngine नहीं, यह एक वाक्यविन्यास त्रुटि होगी। असाइनमेंट एक साधारण कमांड (यानी सिर्फ एक कमांड नेम और कुछ पैरामीटर, और वैकल्पिक रूप से कुछ प्रारंभिक असाइनमेंट और कुछ रीडायरेक्शन) के प्रारंभ में होना चाहिए। A=10; (echo $A)आउटपुट, 10लेकिन Aस्क्रिप्ट के शेष भाग के लिए भी सेट है ।
गिल्स एसओ- बुराई को रोकें '29

2
@EarthEngine लेकिन आप कह सकते हैं A=10 eval 'echo $A'। सिंगल-कोट्स की $Aव्याख्या तब तक की जाती है जब तक कि पूरी लाइन का मूल्यांकन न हो जाए ... तब तक A = 10। मैं इस उत्तर को स्वीकृत से अधिक सही मानता हूं ।
ओली

मुझे लगता है कि यह सही स्पष्टीकरण है। व्यवहार का कारण सिर्फ आदेश है जब का विस्तार $Aऔर असाइनमेंट Aहो रहा है। उदाहरण के लिए A=5; A=6 let 'a=A'; echo $aरिटर्न 6नहीं 5और मुझे नहीं लगता कि letशुरू होता है एक subshell है, क्योंकि यह एक builtin आदेश है।
डेविड ओंगारो

@EarthEngine: जब यह कहा जाता है कि सही स्पष्टीकरण मूल्यांकन का क्रम है, तो यह भ्रामक हो सकता है: बाद में किसी भी आदेश के लिए सेट नहींA=10 echo $A होगा , भले ही वे अलग-अलग लाइनों में हों (जब स्पष्ट रूप से असाइनमेंट का मूल्यांकन किया गया था )। यह ऑर्डर के बारे में नहीं है, यह गुंजाइश के बारे में हैA=10
मेसट्रेलियन

37

जब आप का उपयोग LANG=C gcc ... क्या होता है कि खोल के लिए सेट LANG है gccकी पर्यावरण केवल , और नहीं के लिए वर्तमान वातावरण में ही ( टिप्पणी देखें )। तो gccखत्म होने के बाद , LANGअपने पिछले मूल्य (या परेशान) पर वापस आ जाता है।

इसके अतिरिक्त, जब आप इसका उपयोग A=10 echo $Aकरते हैं तो वह शेल होता है जो $ A की जगह लेता है, न कि प्रतिध्वनि, और इस प्रतिस्थापन (जिसे "विस्तार" कहा जाता है) कथन के मूल्यांकन (असाइनमेंट सहित ) से पहले होता है, इसलिए अपेक्षित रूप से काम करने के Aलिए पहले से ही मूल्य निर्धारित होना चाहिए। में वर्तमान कि बयान करने से पहले पर्यावरण।

इसीलिए A=10 echo $Aअपेक्षित रूप से काम नहीं करता है: A=10इको के लिए सेट किया जाएगा, लेकिन इको आंतरिक रूप से पर्यावरण चर के मूल्य की अनदेखी करता है A। और वर्तमान शेल (जो कोई नहीं है) $Aमें निर्धारित मूल्य के साथ बदल दिया जाता है , और फिर गूंज के तर्क के रूप में पारित किया जाता है।

तो आपकी धारणा सही है: काम VAR=value command करता है , लेकिन यह केवल तभी प्रासंगिक है जब commandआंतरिक रूप से VAR का उपयोग करता है । यदि नहीं, तो आप अभी भी पारित कर सकते हैं valueएक के रूप में तर्क करने के लिए commandहै, लेकिन तर्क की जगह वर्तमान , खोल ताकि वे उपयोग करने से पहले निर्धारित किया जाना चाहिए:VAR=value; command "$VAR"

यदि आप एक निष्पादन योग्य स्क्रिप्ट बनाना जानते हैं, तो आप इसे परीक्षण के रूप में आज़मा सकते हैं:

#!/bin/sh
echo "1st argument is $1"
echo "A is $A"

इसे सहेजें testscriptऔर कोशिश करें:

$ A=5; A=10 testscript "$A"; echo "$A"
1st argument is 5
A is 10
5

अंतिम लेकिन कम से कम, यह शेल और पर्यावरण चर और कार्यक्रम तर्कों के बीच अंतर जानने के लायक है

यहाँ कुछ अच्छे संदर्भ दिए गए हैं:

(*) नोट: तकनीकी रूप से खोल करता भी वर्तमान वातावरण में सेट है, और यहाँ है क्यों: कुछ आदेश, जैसे echo, readऔर testकर रहे हैं खोल builtins , और इस तरह के रूप में वे एक बच्चे की प्रक्रिया अंडे नहीं है। वे वर्तमान परिवेश में चलते हैं। लेकिन शेल केवल असाइनमेंट के लिए ध्यान रखता है जब तक कि कमांड चल रहा है, इसलिए सभी व्यावहारिक उद्देश्यों के लिए प्रभाव समान है: असाइनमेंट केवल उस एकल कमांड द्वारा देखा जाता है।


2
यह स्पष्टीकरण वास्तव में गलत है, हालांकि यह सभी लेकिन कुछ कोने के मामलों में सही निष्कर्ष देता है। वास्तविक स्पष्टीकरण विस्तार का क्रम है: $Aअसाइनमेंट होने से पहले मूल्यांकन किया जाता है। मुझे लगता है कि आपका स्पष्टीकरण केवल नियमित रूप से निर्मित उपयोगिताओं के मामले में विफल रहता है, जिसका व्यवहार चर के मूल्य पर निर्भर करता है: अंतर्निहित मूल्य में निर्दिष्ट मान दिखता है। एक सामान्य उदाहरण है IFS=: read one two three rest, जो बृहदान्त्र-पृथक क्षेत्रों को पढ़ता है: readबिलिन का मान देखता है IFS
गिलेस एसओ- बुराई को रोकें '29

"स्वयं वर्तमान शेल के लिए नहीं" गलत है: चर को वर्तमान शेल में सेट किया गया है, लेकिन यह केवल वर्तमान सरल कमांड के लिए रहता है। अगर इसकी देखभाल की जाती है, तो इसके लिए echoमूल्य देखना होगा । 10A
गिल्स एसओ- बुराई को रोकना '30

@ गिल्स: स्पष्टीकरण के लिए बहुत बहुत धन्यवाद! मुझे इस सूक्ष्मता के बारे में पता नहीं था। इसलिए, अगर मैं सही ढंग से समझ गया, तो बैश को वर्तमान वातावरण के लिए सेट करना होगा अन्यथा बिलिंस (जो एक नया नहीं बनाते हैं pid) असाइनमेंट को अन्य "रेगुलर" कमांड के रूप में नहीं देखेगा। लेकिन यह असाइनमेंट के दायरे को सीमित करने के लिए कमांड के बाद अनिश्चित हो जाता है। क्या यह सही है, मैं अपने उत्तर को ठीक करूंगा। पुनश्च: एक तरफ तकनीकी, मुझे अभी भी लगता है कि एक उत्तर गुंजाइश पहलू पर जोर देना चाहिए, न कि मूल्यांकन आदेश, अन्यथा कोई सोच सकता है कि A=10 test; echo $A10 का प्रिंट होगा
मेस्ट्रेलेयन

3

एक संभवत: स्वच्छ तरीका है जो आप स्पष्ट रूप से इच्छा के लिए आदेश जारी करना चाहते हैं:

A=10 eval 'echo $A'

जो वास्तव में मूल्य ए के प्रतिस्थापन को $ A के स्थान पर बाद के संदर्भ (यानी, 'अंदर', जो पहले से ही असाइनमेंट के बारे में जानता है) के स्थान पर हटा देगा। ध्यान दें कि एकल उद्धरण आवश्यक हैं। इस तरह का निर्माण आपके वर्तमान वातावरण को प्रदूषित करने के जोखिम को चलाने के बिना आपके वांछित कमांड (इस मामले में गूंज) को असाइनमेंट को साफ-साफ बताता है।

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