क्यों बैश में एक कमांड कानूनी से पहले एक चर सेट कर रहा है?


68

मुझे कई उत्तरों का सामना करना पड़ा है जैसे कि एक सीमांकित पाठ फ़ाइल को पार्स करना ... जो निर्माण का उपयोग करता है:

while IFS=, read xx yy zz;do
    echo $xx $yy $zz
done < input_file

जहाँ IFSचर को readकमांड से पहले सेट किया जाता है ।

मैं बैश संदर्भ के माध्यम से पढ़ रहा हूं, लेकिन यह पता नहीं लगा सकता कि यह कानूनी क्यों है।

मैंने कोशिश की

$ x="once upon" y="a time" echo $x $y

बैश कमांड प्रॉम्प्ट से लेकिन कुछ भी नहीं मिला। क्या कोई मुझे बता सकता है कि उस सिंटैक्स को उस संदर्भ में कैसे परिभाषित किया जाता है जो आईएफएस चर को उस तरह से सेट करने की अनुमति देता है? क्या यह एक विशेष मामला है या मैं w / अन्य चर के समान कुछ कर सकता हूं?


जवाबों:


69

यह शेल ग्रामर, सिंपल कमांड्स (जोर जोड़ा) के तहत है:

एक साधारण कमांड वैकल्पिक चर असाइनमेंट का एक क्रम है, जिसके बाद खाली-अलग शब्द और पुनर्निर्देशन होते हैं , और एक नियंत्रण ऑपरेटर द्वारा समाप्त किया जाता है। पहला शब्द कमांड निष्पादित करने के लिए निर्दिष्ट करता है, और तर्क शून्य के रूप में पारित कर दिया है। शेष शब्दों को पारित कमांड में तर्क के रूप में पारित किया जाता है।

इसलिए आप अपने इच्छित किसी भी चर को पास कर सकते हैं। आपका echoउदाहरण काम नहीं करता है क्योंकि चर कमांड में पास किए जाते हैं, शेल में सेट नहीं होते हैं। शेल का विस्तार होता है $xऔर कमांड को लागू करने से $y पहले । यह काम करता है, उदाहरण के लिए:

$ x="once upon" y="a time" bash -c 'echo $x $y'
once upon a time

धन्यवाद! मैंने पूछने से पहले बहुत सारी गुगली की, और यह पता लगाने की कोशिश कर रहा था कि इस संदर्भ में कहा गया है, w / कोई भाग्य नहीं। मैं बैश स्क्रिप्ट लिखने में बेहतर होने की कोशिश कर रहा हूं और आपका जवाब मदद करता है।
माइक लिपर्ट

1
हम्म मुझे लगता है कि मुझे एक बेहतर संदर्भ खोजने की जरूरत है, मेरा (ऊपर लिंक देखें) यह नहीं कहता कि इसमें शेल ग्रामर सेक्शन नहीं है।
माइक लिपर्ट

1
@MikeLippert उस संदर्भ में 3.7.4 देखें ("किसी भी साधारण कमांड या फ़ंक्शन के लिए पर्यावरण को अस्थायी रूप से संवर्धित किया जा सकता है, इसे पैरामीटर असाइनमेंट के साथ प्रीफ़िक्स करके")। मुझे लगता है कि संदर्भ बैश के पुराने संस्करण से है। मैं तो बस दौड़ा man bashअपने सिस्टम पर ...
derobert

29

परिभाषित चर कांटे की प्रक्रिया पर पर्यावरण चर की तरह बन जाते हैं।

अगर तुम दौड़ते हो

A="b" echo $A

फिर बैश पहले में फैलता $Aहै ""और फिर चलता है

A="b" echo

यहाँ सही तरीका है:

x="once upon" y="a time" bash -c 'echo $x $y'

में एकल उद्धरण नोटिस bash -c, अन्यथा आप ऊपर के रूप में एक ही समस्या है।

तो आपका लूप उदाहरण कानूनी है क्योंकि बैश बिलिन 'रीड' कमांड इसके पर्यावरण चर में IFS की तलाश करेगा, और ढूंढेगा ,। इसलिए,

for i in `TEST=test bash -c 'echo $TEST'`
do
  echo "TEST is $TEST and I is $i"
done

छप जाएगा TEST is and I is test

अंत में, सिंटैक्स के लिए, लूप के लिए एक स्ट्रिंग की उम्मीद है। इसलिए मुझे इसे कमांड बनाने के लिए बैकटिक्स का उपयोग करना पड़ा। हालाँकि, जबकि लूप कमांड सिंटैक्स की अपेक्षा करते हैं, जैसे कि IFS=, read xx yy zz


1
धन्यवाद, मैंने आपके उत्तर से जितना पूछा है, उससे थोड़ा अधिक सीखा है। मैं आपके उत्तर को भी वोट करूंगा, लेकिन मुझे अभी तक अनुमति नहीं है और मैंने 1 पर स्वीकृत उत्तर को हरी झंडी दिखाई।
माइक लिपर्ट

1
धन्यवाद, मैं वही हूं जिसकी मुझे उम्मीद थी। और एक वोट आपकी प्रशंसा सुनने की तुलना में कम सार्थक है!
माइक फेयरहर्स्ट

कोड की पहली पंक्ति के तहत अपनी टिप्पणी को स्पष्ट करने के लिए: हां, बिना किसी Aअस्थिर चर के साथ $Aखाली स्ट्रिंग में फैलता है, लेकिन भ्रम से बचने के लिए मैं उपयोग नहीं करूंगा ""क्योंकि कोड के बराबर नहीं है A="b" echo ""। कोई तर्क नहीं होगा echo
पाबूक

8

man bash

वातावरण

[...] किसी भी साधारण कमांड या फंक्शन के लिए वातावरण को पैरामीटर असाइनमेंट के साथ पूर्वनिर्मित करके अस्थायी रूप से संवर्धित किया जा सकता है, जैसा कि PARAMETERS में ऊपर वर्णित है। ये असाइनमेंट स्टेटमेंट केवल उस कमांड द्वारा देखे गए पर्यावरण को प्रभावित करते हैं।

चर असाइनमेंट होने से पहले चर का विस्तार किया जाता है। स्पष्ट कारण जो var=xदूसरे तरीके से काम करेगा, के लिए भी, लेकिन var=$othervarनहीं। यानी $xउपलब्ध होने से पहले आपकी जरूरत है। लेकिन वह मुख्य समस्या नहीं है। मुख्य समस्या यह है कि कमांड लाइन को केवल शेल वातावरण द्वारा संशोधित किया जा सकता है लेकिन असाइनमेंट शेल वातावरण का हिस्सा नहीं बनता है।

आप सुविधाओं में मिलावट करते हैं: आप एक कमांड लाइन प्रतिस्थापन चाहते हैं, लेकिन कमांड की परिभाषा को पर्यावरण में बदल सकते हैं। कमांड लाइन प्रतिस्थापन शेल द्वारा किए जाने हैं। पर्यावरण को स्पष्ट रूप से तथाकथित कमांड द्वारा उपयोग किया जाना चाहिए। यह किया जाता है या नहीं, यह कमांड पर निर्भर करता है।

इस उपयोग का लाभ यह है कि आप शेल पर्यावरण को प्रभावित किए बिना उपप्रोसेस के लिए वातावरण सेट कर सकते हैं।

x="once upon" y="a time" bash -c 'echo $x $y'

जैसा कि आप उम्मीद करते हैं काम करता है क्योंकि उस स्थिति में दोनों विशेषताएं संयुक्त हैं: कमांड लाइन प्रतिस्थापन कॉलिंग शेल द्वारा नहीं किया जाता है, लेकिन उपप्रकार शेल द्वारा।


1
यह उससे थोड़ा अधिक सूक्ष्म है, क्योंकि उदाहरण तब भी काम करता है x="once upon" y="a time" eval 'echo $x $y'जब कोई निर्माण नहीं होता है eval। मुझे लगता है कि मैनपेज से संबंधित उद्धरण है The environment for any simple command or function may be augmented temporarily by prefixing it with parameter assignments। प्रश्न के उदाहरण को देखते हुए यह इस तरह से होना चाहिए क्योंकि readयह एक बिल्डिन भी है और यह अस्थायी रूप से परिवर्तित स्थिति के साथ काम करता है IFS
डेविड ओंगारो

4

आदेश उपलब्ध कराने क्योंकि अलग है $xऔर $yविस्तार कर रहे हैं इससे पहले किecho आदेश रन, इसलिए में उनके मूल्यों वर्तमान खोल उपयोग किया जाता है, नहीं मान जो echoअपने वातावरण में देखना होगा अगर यह देखने के लिए थे।


कमांड चलाने के बाद कमांड लाइन में कुछ भी कैसे बढ़ाया जा सकता है ...?
हउक लागिंग

पूर्व आदेश के कार्य करने के लिए xऔर yवातावरण है कि के लिए कर रहे हैं echoमें, जिसमें तर्क वातावरण नहीं चलाता है, echoका विस्तार कर रहे हैं। के लिए IFS=, read xx yy zz, पूरे स्ट्रिंग को पढ़ा जाता है, readकमांड द्वारा, खोलना । तो फिर , कि स्ट्रिंग के मूल्य के अनुसार विभाजित है IFS, करने के लिए सौंपा इसी टुकड़ों के साथ xx, yy, और zz
chepner

मैं सिर्फ यह बताना चाहता था कि शब्द "कमांड चलने से पहले विस्तारित" का कोई मतलब नहीं है क्योंकि कमांड के शुरू होने के बाद कुछ भी कभी भी अधिक विस्तारित नहीं होता है। इसके अलावा: क्या आपने मेरे जवाब पर एक भी नज़र नहीं डाली है या क्या आप फिर भी मानते हैं कि मुझे क्या हो रहा है, इसका स्पष्टीकरण चाहिए ...?
हौके लैजिंग

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

मामले में echoमुझे यकीन नहीं था कि यह चर को "देख" सकता है, क्योंकि यह एक बिलिन कमांड है और इसलिए यह सब-उप में नहीं चलता है, जिसका अपना वातावरण हो सकता है। लेकिन मैंने इसे आज़माया, evalजिसके साथ एक बिलिन भी है और यह वास्तव में इसके बारे में जानता है। उदाहरण के लिए, a=xyz eval 'echo $BASHPID $a; grep -z ^a /proc/$BASHPID/{,task/*}/environ'; echo $BASHPID $aजो दिखाता है कि aकेवल भीतर ही सेट किया गया है eval, जबकि पिड समान है और पर्यावरण के दौरान परिवर्तन नहीं हुआ है! (एक्सेस के लिए /procआपको लिनक्स के तहत इसे चलाने की आवश्यकता है।) ऐसा लगता है कि बैश यहां कुछ अतिरिक्त जादू करता है।
डेविड ओंगारो

2

मैं " क्यों यह कानूनी है" की बड़ी तस्वीर के लिए जा रहा हूँ

उत्तर: ताकि आप किसी प्रोग्राम को कॉल या इनवॉइस कर सकें और उस इनवोकेशन के लिए केवल एक विशेष वेरिएबल वाले वेरिएबल का उपयोग करें।

एक उदाहरण के रूप में: आपके पास 'db_connection' नामक डेटाबेस कनेक्शन के लिए एक परम है, और आम तौर पर आप अपने परीक्षण डेटाबेस कनेक्शन के नाम के रूप में 'परीक्षण' में पास होते हैं। वास्तव में आप इसे एक डिफ़ॉल्ट के रूप में भी सेट कर सकते हैं जिसे आपको स्पष्ट रूप से पारित करने की आवश्यकता नहीं है। हालांकि कभी-कभी आप ci डेटाबेस के साथ काम करना चाहते हैं। तो आप परम में 'ci' के रूप में पास होते हैं और फिर कहा जा रहा प्रोग्राम उस डेटाबेस परम का उपयोग सभी डेटाबेस कॉल के लिए db के नाम के रूप में करता है। अगले रन के लिए, यदि आप दृष्टिकोण को नहीं दोहराते हैं और प्रोग्राम को कॉल करते हैं तो चर अपने पिछले डिफ़ॉल्ट मान पर वापस आ जाएगा।


0

आप भी इस्तेमाल कर सकते हैं ;। इसका मूल्यांकन पहले किया जाएगा क्योंकि यह कमांड विभाजक है।

x="once upon" y="a time"; echo $x $y

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