2011-10-04 11 views
9

मुझे बैश स्क्रिप्ट में पर्यावरण चर में कुछ कॉन्फ़िगरेशन डेटा पढ़ने की आवश्यकता है।बैश कॉप्रोक और बचे हुए कॉप्रोक आउटपुट

"स्पष्ट" (लेकिन गलत) पैटर्न है:

egrep "pattern" config-file.cfg | read VAR1 VAR2 VAR3 etc... 

यह विफल रहता है क्योंकि read एक subshell में चलाया जाता है और इसलिए प्रेरक खोल में चर सेट नहीं कर सकता। तो मैं इसे वैकल्पिक विकल्प के रूप में आया

coproc egrep "pattern" config-file.cfg 
read -u ${COPROC[0]} VAR1 VAR2 VAR3 etc... 

जो ठीक काम करता है।

परीक्षण करने के लिए क्या होता है अगर coprocess एक से अधिक पंक्ति देता है, मैंने कोशिश की यह:

coproc cat config-file.cfg 
read -u ${COPROC[0]} VAR1 VAR2 VAR3 etc... 

जहां config-file.cfg तीन लाइनों में शामिल है।

$ cat config-file.cfg 
LINE1 A1 B1 C1 
LINE2 A2 B2 C2 
LINE3 A3 B3 C3 

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

$ cat test.sh 
coproc cat config-file.cfg 
read -u ${COPROC[0]} VAR1 VAR2 VAR3 VAR4 
echo $VAR1 $VAR2 $VAR3 $VAR4 
wait 
echo $? 

यह चल रहा है::

$ bash -x test.sh 
+ read -u 63 VAR1 VAR2 VAR3 VAR4 
+ cat config-file.cfg 
LINE1 A1 B1 C1 
+ wait 
+ echo 0 
0 

शेष दो पंक्तियों कहाँ गए थे

तो मैं तो एक स्क्रिप्ट में निम्नलिखित की कोशिश की? मैं या तो "टूटा हुआ पाइप", या wait लटकने की उम्मीद करता था क्योंकि शेष रेखाओं को पढ़ने के लिए कुछ भी नहीं था, लेकिन जैसा कि आप देख सकते हैं कि रिटर्न कोड शून्य था।

+3

जब तक कि मुझे कुछ याद नहीं आ रहा है, 'कुछ पढ़ें VAR1 VAR2 VAR3 <<(egrep "पैटर्न" config-file.cfg)' पर्याप्त होगा, नहीं? –

+0

@ शॉनचिन: यह प्रश्न को अनदेखा कर रहा है। कॉप्रॉक्स अच्छे अच्छे कारण हैं कि ओपी को पहले – sehe

+1

को समझाना नहीं है मेरी अज्ञानता को क्षमा करें। मैं मानता हूं कि कॉप्रॉक्स शांत हैं, लेकिन टिप्पणी एक गुजरने वाले विचार की प्रतिक्रिया थी कि कॉप्रोक्स एक ओवरकिल हो सकता है अगर यह केवल एक सबहेल में चलने और वर्रों को खोने से बचने के लिए है। मैं शायद सामान्य रूप से गलत हूँ। –

उत्तर

5

उपरोक्त टिप्पणियों के अनुसार, आप इसे प्राप्त करने के लिए process substitution का उपयोग कर सकते हैं। इस प्रकार, read एक सबहेल में नहीं चलाया जाता है और कैप्चर किए गए वर्र्स वर्तमान खोल के भीतर उपलब्ध होंगे।

read VAR1 VAR2 VAR3 < <(egrep "pattern" config-file.cfg) 

"< (सूची) फार्म का उपयोग किया जाता है, तो फ़ाइल एक तर्क के रूप में पारित सूची के उत्पादन प्राप्त करने के लिए पढ़ा जाना चाहिए" - क्या "एक agrument के रूप में पारित फ़ाइल" कर रहे हैं वे किसके बारे में बात कर रहे हैं?

यह मेरे लिए भी गूढ़ है।उन्नत बैश-स्क्रिप्टिंग मार्गदर्शिका में chapter on process substitution में एक और व्यापक स्पष्टीकरण है।

तरह से मैं इसे देख, जब <(cmd) वाक्य रचना प्रयोग किया जाता है, cmd के ouput एक नामित पाइप (या अस्थायी फ़ाइल) के माध्यम से उपलब्ध कराया गया है और वाक्य रचना पाइप/फ़ाइल का फ़ाइल नाम से बदल दिया है। ऊपर के उदाहरण के लिए इसलिए, यह के बराबर किया जा रहा अंत होगा:

read VAR1 VAR2 VAR3 < /dev/fd/63 

जहां /dev/fd/63cmd की stdout से जुड़े नामित पाइप है।

+0

बिल्कुल सही, धन्यवाद! मैंने आपके द्वारा प्रदान किए गए लिंक का पालन किया है, और अब यह मेरे स्थायी बैश संदर्भ संग्रह में है :-) –

+0

खुशी है कि मैं मदद कर सकता हूं :) –

2

अगर मैं सही ढंग से अपने प्रश्न समझ में (और मुझे आशा है कि मैं स्पष्ट करते हुए कहा नहीं कर रहा हूँ), पढ़ के रूप में, एक समय में एक लाइन में लिखा है:

$ read a b c < config-file.cfg && echo $? 
0 

या:

$ printf '%s\n%s\n' one two | { read; echo "$REPLY";} 
one 

$ echo ${PIPESTATUS[@]} 
0 0 

सभी इनपुट को पढ़ने के लिए आप एक पाश की आवश्यकता होगी:

$ coproc cat config-file.cfg 
[1] 3460 

$ while read -u ${COPROC[0]} VAR1 VAR2 VAR3; do echo $VAR1 $VAR2 $VAR3; done 
LINE1 A1 B1 C1 
LINE2 A2 B2 C2 
LINE3 A3 B3 C3 
[1]+ Done     coproc COPROC cat config-file.cfg 

बस यह जोड़ने के लिए कि यह FAQ में समझाया गया है।

+1

नहीं, मैं समझता हूं कि 'पढ़ा' एक समय में एक पंक्ति पढ़ता है। मैं क्या सोच रहा था कि जब आप उनमें से केवल एक पढ़ते हैं तो buffered लाइनों के साथ क्या हुआ। मैं एक त्रुटि या लटकने की उम्मीद कर रहा था, लेकिन वे अभी गायब हो गए, जो वास्तव में मैं चाहता हूं, लेकिन मुझे "जादू" से नफरत है जिसे मैं समझ नहीं पा रहा हूं और भविष्यवाणी नहीं कर सकता। –

+0

सह-प्रोप सिर्फ आपके इनपुट को पढ़ने के लिए इंतजार नहीं करता है (बस एक नियमित पाइप की तरह), यह समय समाप्त हो जाता है। निम्नलिखित पर विचार करें: '$ {echo 1; इको 2;} 2' और '$ {echo 1; गूंज 2;} | {पढ़ें; प्रतिलिपि $ प्रतिलिपि; } 1'। 2 कहाँ गए थे? –

+0

तो, उत्तर को सुधारने के लिए: इस मामले में सह-प्रक्रिया निकलती है जब यह अपने इनपुट पर एक अंत-फ़ाइल फ़ाइल देखती है। बार्ट शेफेर ने सह-प्रक्रियाओं पर एक बहुत अच्छा ट्यूटोरियल लिखा, आप इसे यहां देख सकते हैं [यहां] (http://www.zsh.org/mla/users/2011/msg00095.html)। –

संबंधित मुद्दे