बैश में एक कमांड से पहले एक पर्यावरण चर सेट करना एक पाइप में दूसरी कमांड के लिए काम नहीं कर रहा है


351

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

FOO=bar somecommand someargs

यह काम करता है ... तरह का। जब आप एक LC_ * चर को बदल रहे हैं तो यह काम नहीं करता है (जो कमांड को प्रभावित करता है, लेकिन इसके तर्कों को नहीं , उदाहरण के लिए, '[az]' char पर्वतमाला) या जब दूसरी कमांड में आउटपुट को पाइपिंग करता है:

FOO=bar somecommand someargs | somecommand2  # somecommand2 is unaware of FOO

मैं somecommand2 को "FOO = बार" के साथ भी प्रस्तुत कर सकता हूं, जो काम करता है, लेकिन जो अवांछित दोहराव को जोड़ता है, और यह उन तर्कों के साथ मदद नहीं करता है जिनकी व्याख्या चर के आधार पर की जाती है (उदाहरण के लिए, '[az]')।

तो, एक लाइन पर ऐसा करने का एक अच्छा तरीका क्या है?

मैं के आदेश पर कुछ सोच रहा हूँ:

FOO=bar (somecommand someargs | somecommand2)  # Doesn't actually work

मुझे बहुत अच्छे जवाब मिले! लक्ष्य यह "निर्यात" का उपयोग किए बिना अधिमानतः एक-लाइनर रखने के लिए है। बैश के लिए एक कॉल का उपयोग करने का तरीका समग्र रूप से सबसे अच्छा था, हालांकि इसमें "निर्यात" के साथ पैतृक संस्करण थोड़ा अधिक कॉम्पैक्ट था। पाइप के बजाय पुनर्निर्देशन का उपयोग करने का तरीका दिलचस्प है।


1
(T=$(date) echo $T)काम करेगा
vp_arth

क्रॉस-प्लेटफ़ॉर्म (इंकलाब विंडो) स्क्रिप्ट्स या एनपीएम-आधारित परियोजनाओं (जेएस या किसी अन्य) के संदर्भ में, आप क्रॉस-एनवी मॉड्यूल पर एक नज़र डालना चाह सकते हैं ।
फ्रैंक नॉक

5
मैं उम्मीद कर रहा था कि उत्तरों में से एक यह भी बताएगा कि यह एकमात्र प्रकार का कार्य क्यों है, अर्थात यह कॉल से पहले चर को निर्यात करने के बराबर क्यों नहीं है।
ब्रेख्त मैकिएल्स

4
यहाँ क्यों समझाया गया है: stackoverflow.com/questions/13998075/…
ब्रेख्त माचिएल्स

जवाबों:


317
FOO=bar bash -c 'somecommand someargs | somecommand2'

2
यह मेरे मानदंड ("लाइनर" की आवश्यकता के बिना एक-लाइनर को संतुष्ट करता है) ... मुझे लगता है कि "बैश-सी" (जैसे, कोष्ठकों का रचनात्मक उपयोग) को बुलाए बिना ऐसा करने का कोई तरीका नहीं है ?
MartyMacGyver

1
@MartyMacGyver: कोई भी ऐसा नहीं है जिसके बारे में मैं सोच सकता हूं। यह घुंघराले ब्रेसिज़ के साथ भी काम नहीं करेगा।
अगली सूचना तक रोक दिया गया।

7
ध्यान दें कि यदि आपको अपने somecommandसूडो के रूप में चलाने की आवश्यकता है , तो आपको -Eचर को पारित करने के लिए सूडो को पास करने की आवश्यकता है । क्योंकि चर कमजोरियों का परिचय दे सकते हैं। stackoverflow.com/a/8633575/1695680
थोरसुमोनर

11
ध्यान दें कि यदि आपके कमांड में पहले से ही दो स्तरों के उद्धरण हैं तो यह विधि उद्धरण नरक के कारण बेहद असंतोषजनक हो जाती है। उस स्थिति में उपधारा में निर्यात करना ज्यादा बेहतर है।
पुष्पेंद्र्रे

अजीब: OSX पर, FOO_X=foox bash -c 'echo $FOO_X'उम्मीद के मुताबिक काम करता है लेकिन विशिष्ट var नामों से यह विफल रहता है: DYLD_X=foox bash -c 'echo $DYLD_X'echos रिक्त। दोनों के evalबजाय का उपयोग कर कामbash -c
mwag

209

चर के निर्यात के बारे में कैसे, लेकिन केवल उपधारा के अंदर ?:

(export FOO=bar && somecommand someargs | somecommand2)

कीथ के पास एक बिंदु है, बिना शर्त कमांड को निष्पादित करने के लिए, ऐसा करें:

(export FOO=bar; somecommand someargs | somecommand2)

15
मैं इसके ;बजाय का उपयोग करेंगे &&; वहाँ कोई रास्ता नहीं export FOO=barविफल होने जा रहा है।
कीथ थॉम्पसन

1
@MartyMacGyver: &&लेफ्ट कमांड को निष्पादित करता है, फिर दाएं कमांड को निष्पादित करता है तभी लेफ्ट कमांड सफल होता है। ;दोनों आदेशों को बिना शर्त निष्पादित करता है। विंडोज बैच ( cmd.exe) के बराबर ;है &
कीथ थॉम्पसन

2
Zsh में मुझे इस संस्करण के लिए निर्यात की आवश्यकता नहीं है: (FOO=XXX ; echo FOO=$FOO) ; echo FOO=$FOOपैदावार FOO=XXX\nFOO=\n
रैंप

3
@PopePupinpants: उस मामले में source(उर्फ .) का उपयोग क्यों नहीं किया गया ? इसके अलावा, इन दिनों बैकटिक्स का उपयोग नहीं किया जाना चाहिए और यह एक कारण है कि, $(command)वहाए सुरक्षित का उपयोग क्यों कर रहा है।
0xC0000022L

3
इतना सरल, फिर भी इतना सुरुचिपूर्ण। और मुझे आपका उत्तर स्वीकार किए गए उत्तर से बेहतर लगता है, क्योंकि यह मेरे वर्तमान के बराबर एक उप शेल शुरू करेगा (जो नहीं हो सकता है, bashलेकिन कुछ और हो सकता है, जैसे dash) और मैं किसी भी परेशानी में नहीं भागता अगर मुझे उद्धरण का उपयोग करना चाहिए कमांड आर्ग्स के भीतर ( someargs)।
मेकी

45

आप यह भी उपयोग कर सकते हैं eval:

FOO=bar eval 'somecommand someargs | somecommand2'

चूँकि यह उत्तर evalसभी को खुश करने के लिए नहीं है, इसलिए मुझे कुछ स्पष्ट करने दें: जब लिखित रूप में उपयोग किया जाता है, तो एकल उद्धरण के साथ , यह पूरी तरह से सुरक्षित है। यह अच्छा है क्योंकि यह एक बाहरी प्रक्रिया (जैसे स्वीकार किए गए उत्तर) को लॉन्च नहीं करेगा और न ही यह एक अतिरिक्त उपधारा में आदेशों को निष्पादित करेगा (अन्य उत्तर की तरह)।

जैसा कि हम कुछ नियमित विचार प्राप्त करते हैं, यह संभवतः एक विकल्प देने के लिए अच्छा है evalजो सभी को खुश करेगा, और इस त्वरित eval"चाल" के सभी लाभ (और शायद और भी अधिक!) होंगे । बस एक फ़ंक्शन का उपयोग करें! अपने सभी कमांड के साथ एक फंक्शन को परिभाषित करें:

mypipe() {
    somecommand someargs | somecommand2
}

और इसे अपने पर्यावरण चर के साथ इस तरह निष्पादित करें:

FOO=bar mypipe

7
@ शेल्फ: क्या आपने भी स्वीकृत उत्तर को रद्द कर दिया है? क्योंकि यह उसी "समस्याओं" को प्रदर्शित करता है eval
ग्नौरफ_ग्निऑरफ

10
@Alfe: दुर्भाग्य से मैं आपकी आलोचना से सहमत नहीं हूँ। यह कमांड पूरी तरह से सुरक्षित है। आप वास्तव में उस आदमी की तरह आवाज़ करते हैं जो एक बार पढ़ evalलेता है, यह समझने के बिना कि यह बुराई क्या है eval। और हो सकता है कि आप वास्तव में इस उत्तर को बिल्कुल नहीं समझ रहे हों (और वास्तव में इसमें कुछ भी गलत नहीं है)। उसी स्तर पर: क्या आप कहेंगे कि lsबुरा है क्योंकि for file in $(ls)बुरा है? (और हाँ, आपने स्वीकृत उत्तर को अस्वीकार नहीं किया है, और आपने कोई टिप्पणी नहीं छोड़ी है)। एसओ कभी-कभी ऐसी अजीब और बेतुकी जगह है।
गनीउरफ_गनीउरफ

7
@Alfe: जब मैं कहता हूं कि आप वास्तव में एक आदमी की तरह आवाज करते हैं, जो एक बार पढ़ evalलेता है, तो यह समझने के बिना कि यह क्या बुराई है eval, मैं आपकी सजा का जिक्र कर रहा हूं: यह उत्तर उन सभी चेतावनियों और स्पष्टीकरणों का अभाव है eval , जिनके बारे में बात करना आवश्यक है evalबुरा या खतरनाक नहीं है; से अधिक नहीं bash -c
गनीउरफ_निगियॉर्फ

1
एक तरफ वोट, @Alfe प्रदान की गई टिप्पणी किसी भी तरह का मतलब है कि स्वीकृत जवाब किसी तरह सुरक्षित है। आपके द्वारा उपयोग किए जाने के बारे में असुरक्षित होने के बारे में आपका वर्णन करने के लिए आपके लिए अधिक उपयोगी क्या होगा eval। उत्तर में, प्रदान किए गए आर्गल्स को चर विस्तार से सुरक्षित रखते हुए उद्धृत किया गया है, इसलिए मुझे उत्तर के साथ कोई समस्या नहीं है।
ब्रेट रयान

मैंने अपनी टिप्पणियों को एक नई टिप्पणी में अपनी चिंता को केंद्रित करने के लिए हटा दिया: evalसामान्य रूप से एक सुरक्षा मुद्दा है (जैसे कि bash -cकम स्पष्ट), लेकिन इसके उपयोग का प्रस्ताव करने वाले उत्तर में खतरों का उल्लेख किया जाना चाहिए। लापरवाह उपयोगकर्ता इसका जवाब दे सकते हैं ( FOO=bar eval …) और इसे अपनी स्थिति पर लागू कर सकते हैं ताकि यह समस्या खड़ी करे। लेकिन यह स्पष्ट रूप से उत्तर देने वाले के लिए अधिक महत्वपूर्ण था कि मैं कुछ सुधार करने की तुलना में उसके और / या अन्य उत्तरों को हटा दूं या नहीं। जैसा कि मैंने पहले लिखा था, निष्पक्षता मुख्य चिंता नहीं होनी चाहिए; किसी भी अन्य दिए गए उत्तर से भी बदतर नहीं होने के बावजूद भी अप्राकृतिक है।
अल्फ

12

का उपयोग करें env

उदाहरण के लिए, env FOO=BAR command। ध्यान दें कि जब commandक्रियान्वयन समाप्त हो जाता है तो पर्यावरण चर फिर से बहाल / अपरिवर्तित हो जाएंगे ।

बस शेल प्रतिस्थापन होने के बारे में सावधान रहें, अर्थात यदि आप $FOOसमान कमांड लाइन पर स्पष्ट रूप से संदर्भ देना चाहते हैं, तो आपको इसे भागने की आवश्यकता हो सकती है ताकि आपके शेल दुभाषिया प्रतिस्थापन को चलाने से पहले प्रदर्शन न करें env

$ export FOO=BAR
$ env FOO=FUBAR bash -c 'echo $FOO'
FUBAR
$ echo $FOO
BAR

-5

एक शेल स्क्रिप्ट का उपयोग करें:

#!/bin/bash
# myscript
FOO=bar
somecommand someargs | somecommand2

> ./myscript

13
आपको अभी भी ज़रूरत है export; अन्यथा $FOOएक खोल चर, न कि एक वातावरण चर, और इसलिए करने के लिए नहीं दिखाई देंगे somecommandया somecommand2
कीथ थॉम्पसन

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