वर्तमान शेल के भीतर कमांड के आउटपुट को कैसे निष्पादित करें?


89

मैं अच्छी तरह से source(उर्फ .) उपयोगिता से अवगत हूं , जो एक फ़ाइल से सामग्री ले जाएगा और उन्हें मौजूदा शेल के भीतर निष्पादित करेगा।

अब, मैं कुछ पाठों को शेल कमांड में बदल रहा हूं, और फिर उन्हें निम्न प्रकार से चला रहा हूं:

$ ls | sed ... | sh

lsकेवल एक यादृच्छिक उदाहरण है, मूल पाठ कुछ भी हो सकता है। sedभी, केवल पाठ को बदलने के लिए एक उदाहरण। दिलचस्प बिट है sh। मुझे जो कुछ भी मिला मैं उसे पाइप करता हूं shऔर इसे चलाता है।

मेरी समस्या है, इसका मतलब है कि एक नया उप शेल शुरू करना। मैं बल्कि अपने वर्तमान शेल के भीतर कमांड चलाना चाहता हूं। जैसे मैं source some-fileएक पाठ फ़ाइल में आज्ञाओं के साथ कर सकता हूं।

मैं एक अस्थायी फ़ाइल नहीं बनाना चाहता क्योंकि गंदा लगता है।

वैकल्पिक रूप से, मैं अपने वर्तमान शेल के समान सटीक विशेषताओं के साथ अपना उप शेल प्रारंभ करना चाहूंगा।

अपडेट करें

ठीक है, बैकटीक का उपयोग करने वाले समाधान निश्चित रूप से काम करते हैं, लेकिन मुझे अक्सर ऐसा करने की आवश्यकता होती है जब मैं जाँच कर रहा हूं और आउटपुट बदल रहा हूं, इसलिए मैं बहुत पसंद करूंगा यदि परिणाम को अंत में किसी चीज में पाइप करने का कोई तरीका हो।

दुखद अद्यतन

आह, /dev/stdinबात बहुत सुंदर लग रही थी, लेकिन, एक अधिक जटिल मामले में, यह काम नहीं किया।

तो, मेरे पास यह है:

find . -type f -iname '*.doc' | ack -v '\.doc$' | perl -pe 's/^((.*)\.doc)$/git mv -f $1 $2.doc/i' | source /dev/stdin

यह सुनिश्चित करता है कि सभी .docफाइलों का विस्तार कम हो।

और जो संयोगवश, के साथ संभाला जा सकता है xargs, लेकिन वह बिंदु के अलावा है।

find . -type f -iname '*.doc' | ack -v '\.doc$' | perl -pe 's/^((.*)\.doc)$/$1 $2.doc/i' | xargs -L1 git mv

इसलिए, जब मैं पूर्व भागता हूं, तो यह तुरंत बाहर निकल जाएगा, कुछ भी नहीं होता है।


जब आप किसी अस्थायी फ़ाइल पर पहले पाइप करते हैं और फिर उसे स्रोत करते हैं तो क्या आपकी जटिल कमांड काम करती है? यदि नहीं, तो उत्पन्न आउटपुट में क्या समस्या है? यदि आपके फ़ाइल नाम में जगह है या कुछ क्रम ठीक से बच नहीं रहे हैं तो आपके कमांड का आउटपुट काम नहीं करेगा। मैं कम से कम $ 1 और $ 2.doc के बारे में उद्धरण जोड़ना चाहता हूं।
कालेब पेडरसन

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

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

स्रोत / देव / स्टड ने मेरे लिए काम नहीं किया जब जरूरत पड़ने पर चर चरने की जरूरत थी। जिरिहा ऑन फ्रीनोड बैश ने मुझे mywiki.wooledge.org/BashFAQ/024 की ओर इशारा किया और सुझाव दिया कि मैं एक प्रक्रिया प्रतिस्थापन स्रोत <(कमांड) की कोशिश करूं जो मेरे लिए काम करे
srcerer

जवाबों:


85
$ ls | sed ... | source /dev/stdin

UPDATE: यह bash 4.0, साथ ही tsh, और डैश (यदि आप बदलते sourceहैं .) में काम करता है। जाहिरा तौर पर यह बैश 3.2 में छोटी गाड़ी थी। से बैश 4.0 रिलीज नोट्स :

एक बग को ठीक किया गया जो `। उपकरणों या नामित पाइप जैसी गैर-नियमित फ़ाइलों से आदेशों को पढ़ने और निष्पादित करने में विफल।


ठीक। 4.0 पर फिर बैश करें।
kch

ओह, और जब से आप गोले सूचीबद्ध कर रहे हैं, यह zsh में भी काम करता है।
kch

1
मैंने सोचा कि यह सरल था जब तक मैंने इसे msys / mingw (जहाँ कोई / dev फ़ोल्डर (या यहाँ तक कि डिवाइस भी नहीं है) में आज़माया! मैंने eval, $ () और backticks के कई संयोजनों की कोशिश की ``। मैं कुछ भी काम नहीं कर सका। , तो मैं अंत में सिर्फ एक अस्थायी फ़ाइल में आउटपुट पुनर्निर्देशित, अस्थायी फ़ाइल sourced, और इसे हटा दिया। मूल रूप से "sed ...> /tmp/$$.tmp && .tt//$$.tmp && rm / tmp /। ।। $$ tmp "किसी एक msys / अस्थायी फ़ाइलों के बिना MinGW समाधान ??? मिला
chriv

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

1
यह देखते हुए कि मैकओएस एक्स में आमतौर पर 3.2 बैश होता है (शायद योसेमाइट में 4.0 है?), और मेरे उपयोग के मामले में लास्ट ट्राइपरी की आवश्यकता है ('एक्सपेरिमेंट' जोड़ने के लिए प्रत्येक लाइन को प्री-प्रोसेसिंग करके फाइल में सभी वेरिएबल्स को प्री-प्रोसेस करके निर्यात करें) eval "$(sed ...)"दृष्टिकोण के साथ जाने के लिए - लेकिन 3.2 बग सिर के लिए धन्यवाद!
एलेक्स डुप्यू

133

evalआदेश यह बहुत ही उद्देश्य के लिए मौजूद है।

eval "$( ls | sed... )"

बैश मैनुअल से अधिक :

eval

          eval [arguments]

तर्कों को एक ही आदेश में एक साथ समाहित किया जाता है, जिसे तब पढ़ा जाता है और निष्पादित किया जाता है, और इसके निकास की स्थिति निकासी के निकास की स्थिति के रूप में वापस आ जाती है। यदि कोई तर्क या केवल खाली तर्क नहीं हैं, तो वापसी की स्थिति शून्य है।


8
यहाँ एकमात्र मुद्दा यह है कि आपको अपनी आज्ञाओं को अलग करने के लिए सम्मिलित करने की आवश्यकता हो सकती है। मैं AIX, Sun, HP और Linux पर काम करने के लिए इस विधि का उपयोग स्वयं करता हूं।
टंकटालस

टंकटालस, उस टिप्पणी के लिए धन्यवाद, यह सिर्फ मेरी स्क्रिप्ट का काम करता है। मेरी मशीन के बाहर होने पर न्यूलाइन्स पर अलग-अलग कमांड नहीं होते हैं और स्रोत का उपयोग करने से सेमी-कॉलन के साथ भी काम नहीं होता है। अर्ध-कोलोन के साथ ईविल समाधान है। काश मैं आपको कुछ बिंदु दे पाता।
मिलन बाबुकोव

2
@ मिलनबुआकोव: मैंने उसे आपके लिए स्थान दिया ;-)
फिल

3
यह उत्कृष्ट है। हालांकि, मेरे उपयोग के मामले के लिए, मैंने अपने $ () के आसपास उद्धरण देने के लिए समाप्त किया, जैसे: eval "$( ssh remote-host 'cat ~/.bash_profile' )"ध्यान दें कि मैं वास्तव में bash 3.2 का उपयोग कर रहा हूं।
ज़ाचरी मरे

3
यह मेरे लिए काम करता है जहां स्वीकृत उत्तर नहीं था।
डैन तेनबाउम

37

वाह, मुझे पता है कि यह एक पुराना सवाल है, लेकिन मैंने हाल ही में खुद को उसी सटीक समस्या के साथ पाया है (यही कारण है कि मैं यहां आया हूं)।

वैसे भी - मुझे source /dev/stdinजवाब पसंद नहीं है , लेकिन मुझे लगता है कि मैंने एक बेहतर पाया। यह वास्तव में भ्रामक है:

echo ls -la | xargs xargs

अच्छा लगा ना? वास्तव में, यह अभी भी वही नहीं करता है जो आप चाहते हैं, क्योंकि यदि आपके पास कई लाइनें हैं, तो यह प्रत्येक कमांड को अलग-अलग चलाने के बजाय उन्हें एक ही कमांड में सम्‍मिलित करेगा। तो मुझे जो हल मिला वो है:

ls | ... | xargs -L 1 xargs

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

अंत में, आप कर सकते हैं

ls | ... | xargs -L 1 xargs -t

यह देखने के लिए कि क्या कमांड निष्पादित हैं (-t क्रिया है)।

आशा है कोई इसे पढ़े!


30

प्रक्रिया प्रतिस्थापन का उपयोग करने का प्रयास करें , जो एक अस्थायी फ़ाइल के साथ एक कमांड के आउटपुट को बदलता है जिसे तब खट्टा किया जा सकता है:

source <(echo id)

7
यह किस प्रकार का टोना है?
पौलोटरेन्स

यह मेरा पहला विचार था। हालांकि मुझे eval solution ज्यादा अच्छा लगता है। @PauloTorrens <(xyz) केवल xyz को निष्पादित करता है और <(xyz) को एक फ़ाइल के नाम से बदलता है जो xyz के आउटपुट को लिखेगा। यह समझना बहुत आसान है कि उदाहरण के लिए यह कैसे काम करता है: echo <(echo id)आउटपुट दे रहा है /dev/fd/12(12 एक उदाहरण है), cat <(echo id)आउटपुट दे रहा है id, और फिर source <(echo id)उसी आउटपुट को केवल लिखने के रूप में दे रहा हैid
netigger

2
@PauloTorrens, इसे प्रक्रिया प्रतिस्थापन कहते हैं । आधिकारिक स्पष्टीकरण के लिए लिंक किए गए डॉक्स देखें, लेकिन संक्षिप्त उत्तर यह है कि "<()" एक विशेष वाक्यविन्यास है जो इस तरह के मामलों को ध्यान में रखकर बनाया गया था।
मार्क स्टोसबर्ग

1
@MarkStosberg, क्या आपको पता है कि यह एक विशेष वाक्यविन्यास है, या सिर्फ एक उप- (...)पुनर्निर्देशित है?
पॉलोटरेन्स

2
@PauloTorrens, यह प्रक्रिया प्रतिस्थापन के लिए एक विशेष वाक्यविन्यास है।
मार्क स्टोसबर्ग 1

6

मेरा मानना ​​है कि यह प्रश्न का "सही उत्तर" है:

ls | sed ... | while read line; do $line; done

यही है, एक whileलूप में पाइप कर सकता है ; readआदेश आदेश अपने से एक लाइन लेता है stdinऔर चर करने के लिए इसे प्रदान करती है $line$lineफिर लूप के भीतर निष्पादित कमांड बन जाता है; और यह तब तक जारी रहता है जब तक इसके इनपुट में आगे की लाइनें न हों।

यह अभी भी कुछ नियंत्रण संरचनाओं (दूसरे लूप की तरह) के साथ काम नहीं करेगा, लेकिन यह इस मामले में बिल फिट बैठता है।


5
`ls | sed ...`

मुझे ऐसा लगता है कि ls | sed ... | source -यह बहुत अच्छा होगा, लेकिन दुर्भाग्य से इसका मतलब sourceसमझ में नहीं आता -है stdin


mark4o का उत्तर देखने के बाद, क्या यह महसूस नहीं होता है कि यह इस समय हमारे चेहरे पर सही था?
kch

हे, हाँ। मुझे याद नहीं है कि सामान मौजूद है।
अराजकता

1

मुझे लगता है कि आपका समाधान backticks के साथ कमांड प्रतिस्थापन है: http://tldp.org/LDP/Bash-Beginners-Guide/html/sect_03_04.html

अनुभाग 3.4.5 देखें


3
यदि आप बैश का उपयोग कर रहे हैं तो $( )सिंटैक्स पसंद किया जा सकता है। 'कोर्स बैकटिक्स अधिक गोले में काम करते हैं ...
dmckee --- पूर्व-मध्यस्थ बिल्ली का बच्चा

6
$ (कमांड) और $ ((1 + 1)) सभी पॉज़िक्स गोले में काम करते हैं। मुझे लगता है कि बहुतों को सिंटैक्स त्रुटियों के रूप में चिह्नित करके विम से हटा दिया जाता है, लेकिन यह सिर्फ इसलिए है क्योंकि विम मूल बॉर्न शेल के लिए हाइलाइटिंग है जो बहुत कम उपयोग करता है। इसे ठीक से हाइलाइट करने के लिए अपने .vimrc: let: g: is_posix = 1
पिक्सेलबीट

1

बैश 3.2 (मैकोस) पर मार्को 4 के समाधान का उपयोग करने के लिए इस तरह की पाइपलाइनों के बजाय यहां स्ट्रिंग का उपयोग किया जा सकता है:

. /dev/stdin <<< "$(grep '^alias' ~/.profile)"

या backticks का उपयोग करें:। / dev / stdin <<< `grep '^ उपनाम' ~ / .profile`
विलियम एच। हूपर

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