मैं कमांड लाइन पर एक पर्यावरण चर कैसे सेट कर सकता हूं और क्या यह कमांड में दिखाई देता है?


151

अगर मैं चला

export TEST=foo
echo $TEST

यह फू का उत्पादन करता है।

अगर मैं चला

TEST=foo echo $TEST

ऐसा नहीं होता। मैं निर्यात या स्क्रिप्ट का उपयोग किए बिना यह कार्यक्षमता कैसे प्राप्त कर सकता हूं?


सावधान, शुरू में दिखाई देने की तुलना में इस कहानी में अधिक है। मैं आपको अपना उत्तर जाँचने के लिए आमंत्रित करता हूँ।
jasonleonhard

जवाबों:


179

ऐसा इसलिए है क्योंकि शेल कमांड लाइन में चर का विस्तार करता है इससे पहले कि वह वास्तव में कमांड चलाता है और उस समय चर मौजूद नहीं है। यदि तुम प्रयोग करते हो

TEST=foo; echo $TEST

यह काम करेगा।

exportचर को बाद में निष्पादित आदेशों के वातावरण में दिखाई देगा (यह कैसे काम करता है इस पर देखें help export)। यदि आपको केवल एक कमांड के वातावरण में चर की आवश्यकता है, तो आपने जो प्रयास किया है, उसका उपयोग करें:

TEST=foo your-application

1
/ Usr / bin / env के बारे में क्या? यह भी काम नहीं करता है, क्या आप जानते हैं क्यों?
बेनुबर्ड

5
समान कारण - $TESTकमांड लाइन निष्पादित होने से पहले शेल का विस्तार होता है। एक बार echoचल रहा है (यह भी ध्यान दें कि echoआमतौर पर शेल में अंतर्निहित कमांड में अनुवाद होगा और नहीं /bin/echo) यह अपने वातावरण में चर सेट को देखता है। हालांकि, इसके वातावरण से चर की सामग्री का उत्पादन करने के लिए echo $TESTनहीं कहता है। यह शेल को तर्क के साथ चलने के लिए कहता है जो वर्तमान में चर में है - और वे दो बहुत अलग चीजें हैं। echoTESTechoTEST
पीटर जूल 9'14

@peterph यदि शेल कमांड लाइन में चर का विस्तार करता है इससे पहले कि वह वास्तव में कमांड चलाता है तो वह इसमें विस्तार क्यों नहीं करता है var=value sh -c 'echo "$var"'?
haccks

जैसा कि मैंने आपको यहां बताया : यह इसलिए है क्योंकि चर को दोहरे उद्धरण चिह्नों (जैसे "… $var …") के अंदर विस्तारित किया जाता है, लेकिन एकल उद्धरणों (जैसे, '… $var …') के अंदर नहीं । चूंकि echo "$var"सिंगल कोट्स के अंदर है, इसलिए पूरे स्ट्रिंग sh -cको बाहरी, इंटरेक्टिव शेल द्वारा व्याख्या किए बिना नए ( ) शेल में पास किया जाता है । … (Cont'd)
G-Man

(Cont'd) ... जैसा कि कल igal ने कहा , पार्सिंग के दो दौर हैं - हालांकि मेरा मानना ​​है कि इगल ने अपने सवाल को गलत बताया। पैरस शेल द्वारा किए गए पार्सिंग के अलावा पार्सिंग के दो राउंड नहीं होते हैं । पार्सिंग के दो दौर होते हैं - एक बाहरी, संवादात्मक (माता-पिता) शेल द्वारा किया जाता है, और एक नए ( sh -c) चाइल्ड शेल द्वारा किया जाता है।
जी-मैन

39

मुझे संदेह है कि आप पर्यावरण चर की बजाय एक सीमित दायरे के लिए शेल चर रखना चाहते हैं । पर्यावरण चर, कमांड के लिए पारित तार की एक सूची है जब उन्हें निष्पादित किया जाता है

में

var=value echo whatever

आप var=valueस्ट्रिंग को उस वातावरण में पास कर रहे हैं जो गूंज प्राप्त करता है। हालाँकि, echoअपनी पर्यावरण सूची के साथ कुछ भी नहीं करता है और वैसे भी अधिकांश गोले echoमें बनाया जाता है और इसलिए इसे निष्पादित नहीं किया जाता है

अगर आपने लिखा होता

var=value sh -c 'echo "$var"'

यह एक और मामला होता। यहाँ, हम गुजर रहे हैं var=valueकरने के लिए shआदेश, और shअपने पर्यावरण के उपयोग करने के लिए होता है। गोले अपने वातावरण से प्राप्त होने वाले प्रत्येक चर को शेल चर में परिवर्तित करते हैं, इसलिए varपर्यावरण चर shप्राप्त करने वाले को एक $varचर में परिवर्तित किया जाएगा , और जब यह उस echoकमांड लाइन में फैलता है, तो यह बन जाएगा echo value। क्योंकि पर्यावरण डिफ़ॉल्ट रूप से विरासत में मिला है, इसके वातावरण में echoभी प्राप्त var=valueहोगा (या यदि इसे निष्पादित किया गया था), लेकिन फिर से, echoपर्यावरण के बारे में परवाह नहीं करता है।

अब, यदि मुझे संदेह है, तो आप जो चाहते हैं वह शेल चरों के दायरे को सीमित करना है, कई संभावित दृष्टिकोण हैं।

आंशिक रूप से (Bourne और POSIX):

(var=value; echo "1: $var"); echo "2: $var"

ऊपर (...) एक उप-शेल (अधिकांश शेल में एक नई शेल प्रक्रिया) शुरू करता है, इसलिए वहां घोषित कोई भी वेरिएबल केवल उस उप-शेल को प्रभावित करेगा, इसलिए मुझे उपरोक्त कोड "1: मान" की उम्मीद होगी और "2:" या "2: जो भी- var-was-set-to-before" था।

अधिकांश बॉर्न-जैसे गोले के साथ, आप फ़ंक्शंस और "स्थानीय" बिलिन का उपयोग कर सकते हैं:

f() {
  local var
  var=value
  echo "1: $var"
}
f
echo "2: $var"

Zsh के साथ, आप इनलाइन फ़ंक्शन का उपयोग कर सकते हैं:

(){ local var=value; echo "1: $var"; }; echo "2: $var"

या:

function { local var=value; echo "1: $var"; }; echo "2: $var"

बैश और zsh के साथ (लेकिन राख, pdksh या AT & T ksh नहीं), यह ट्रिक भी काम करती है:

var=value eval 'echo "1: $var"'; echo "2: $var"

एक संस्करण है कि कुछ और गोले में काम करता है ( dash, mksh, yash), लेकिन नहीं zsh(जब तक में sh/ kshअनुकरण):

var=value command eval 'echo "1: $var"'; echo "2: $var"

( POSIX गोले में commandएक विशेष बिलिन (यहाँ eval) के सामने उपयोग करने से उनकी ख़ासियत दूर हो जाती है (यहाँ से वे चर असाइनमेंट वापस आने के बाद प्रभाव में रहते हैं)


मेरे उद्देश्यों के लिए, यह सही समाधान है। मैं नहीं चाहता कि चर 'var' पर्यावरण को प्रदूषित करे क्योंकि यह स्वीकृत उत्तर में है।
क्रोनेंपज

6

आप इसे सही तरीके से कर रहे हैं, लेकिन बैश सिंटैक्स गलत व्याख्या करना आसान है: आप सोच सकते हैं कि env var लाने का echo $TESTकारण बनता echoहै TESTतब इसे प्रिंट करें, ऐसा नहीं है। तो दिया

export TEST=123

फिर

TEST=456 echo $TEST

निम्नलिखित अनुक्रम शामिल है:

  1. शेल पूरी कमांड लाइन को पार्स करता है और सभी वैरिएबल सबस्टेशनों को निष्पादित करता है, इसलिए कमांड लाइन बन जाती है

    TEST=456 echo 123
  2. यह कमांड के पहले टेम्प वर्सेस बनाता है, इसलिए यह TEST456 के साथ वर्तमान मूल्य को बचाता है और इसे अधिलेखित करता है; कमांड लाइन अब है

    echo 123
  3. यह शेष कमांड को निष्पादित करता है, जो इस मामले में 123 को stdout में प्रिंट करता है (इसलिए शेल कमांड जो अवशेष भी मंदिर के मूल्य का उपयोग नहीं करता है TEST)

  4. यह के मूल्य को पुनर्स्थापित करता है TEST

इसके बजाय प्रिंटेनव का उपयोग करें, क्योंकि इसमें चर प्रतिस्थापन शामिल नहीं है:

>> export TEST=123
>> printenv TEST
123
>> TEST=456 printenv TEST
456
>> printenv TEST && TEST=456 printenv TEST && TEST=789 printenv TEST && printenv TEST
123
456
789
123
>>

+1 मैंने printenvअवधारणा के परीक्षण / प्रमाण के लिए सहायक पाया (एक स्क्रिप्ट जैसा व्यवहार करता है, जैसा कि विरोध किया जाता है echo)
डेरिन

5

आप इसका उपयोग करके काम कर सकते हैं:

TEST=foo && echo $TEST

6
इस मामले में, TEST=fooएक अलग बयान के रूप में चल रहा है - यह केवल के संदर्भ में निर्धारित नहीं है echo
19for पर कोडरस्टर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.