2012-08-28 13 views
6

मैं एक लूप के भीतर बैश उपनाम बनाना चाहता हूं जहां लूप कमांड से लाइनें पढ़ रहा है। आउटपुट लाइन-बाय-लाइन पढ़ने के लिए, मुझे विश्वास है कि मुझे आउटपुट को read में पाइप करने की आवश्यकता है। जब मैं ऐसा करता हूं, हालांकि, उपनाम मौजूद नहीं हैं।मैं थोड़ी देर के अंदर क्यों नहीं खोल सकता?

अगर मैं अपने .bashrc में निम्नलिखित शामिल हैं:

for x in a1 a2; do 
    eval "alias $x='echo foo'" 
done 

echo -e "a3\na4" | while read x; do 
    eval "alias $x='echo foo'" 
done 

उपनाम a1 और a2 मौजूद हैं, लेकिन a3 और a4 नहीं है। उन दो loops के बीच क्या अंतर है?

+0

यह एक बहुत आम गॉचा है जब 'लूप' पर पाइपिंग होता है। [यह उत्तर] देखें (http://stackoverflow.com/questions/7612320/bash-weird-variable-scope-when-populating-array-with-results/7612420#7612420), या [BashFAQ/024] (http: //mywiki.wooledge.org/BashFAQ/024) विवरण और विभिन्न वैकल्पिक समाधानों के लिए। –

+5

इसके अलावा, यहां 'eval' का उपयोग करने की कोई आवश्यकता नहीं है। उपनाम परिभाषित करने से पहले 'xias $ x = 'echo foo'' 'x x 'का विस्तार करेगा। – chepner

उत्तर

5

समस्या पाइपलाइन है। a | b | c के प्रत्येक पाइपलाइन में, प्रत्येक व्यक्तिगत आदेश a, b, और c एक अलग सबहेल [ ref] में चलाया जाता है, जिसका अर्थ है कि इसे माता-पिता के निष्पादन वातावरण (उपनाम सहित) की एक प्रति प्राप्त होती है, और इसमें कोई भी परिवर्तन होता है अपनी प्रतिलिपि बनाता है (जैसे alias चलाकर) माता-पिता [ ref] पर कोई प्रभाव नहीं पड़ेगा।

आपके मामले में, आप लेखन करके इसे ठीक कर सकते हैं:

while read x; do 
    eval "alias $x='echo foo'" 
done < <(echo -e "a3\na4") 

जो अभी भी एक subshell में echo -e "a3\na4" चलेगा, लेकिन सामान्य/माता-पिता निष्पादन वातावरण में while -loop चलेंगे।

+0

मैंने पहले '<(कमांड)' वाक्यविन्यास नहीं देखा है। क्या यह 'आदेश' के आउटपुट को इंगित करने वाला फ़ाइल डिस्क्रिप्टर बना रहा है? –

+0

@ जेफक्लुकस: हाँ; इसे "प्रक्रिया प्रतिस्थापन" कहा जाता है (देखें http://www.gnu.org/software/bash/manual/bashref.html#Process- सबस्टिट्यूशन), और यह या तो एक फीफो या '/ dev/fd' फ़ाइल का उपयोग करता है। दस्तावेज़ीकरण का तात्पर्य है कि यह सभी प्रणालियों पर काम नहीं करता है, लेकिन यह सिगविन समेत सभी प्रणालियों पर काम करता है। – ruakh

6

पाइप में जबकि लूप एक सबहेल में चलता है। आप कर सकते हैं:

while read x; do 
    eval "alias $x='echo foo'" 
done << EOF 
a3 
a4 
EOF 
3

बैश 4.2 में और बाद में, आप एक subshell में क्रियान्वित करने से पिछले एक पाइप की कमान रखने के लिए lastpipe विकल्प सेट कर सकते हैं। काम करने के लिए नौकरी नियंत्रण भी बंद होना चाहिए (set +m)।

shopt -s lastpipe 
set +m 
echo -e "a3\na4" | while read x; do 
    alias $x='echo foo' 
done 
+0

+1: जानना अच्छा है! – ruakh

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