tl; डॉ
एक एकमात्र सबसे शायद आपके लिए काम stuff
करेगा ।
पूरा जवाब
क्या होता है
जब आप दौड़ते हैं foo $(stuff)
, तो यही होता है:
stuff
रन;
- इसका आउटपुट (स्टडआउट) मुद्रित होने के बजाय,
$(stuff)
के मंगलाचरण में बदल जाता है foo
;
- फिर
foo
चलता है, इसके कमांड लाइन तर्क स्पष्ट रूप से इस बात पर निर्भर करते हैं कि क्या stuff
लौटा।
इस $(…)
तंत्र को "कमांड प्रतिस्थापन" कहा जाता है। आपके मामले में मुख्य आदेश हैecho
जो मूल रूप से अपने कमांड लाइन तर्कों को स्टडआउट करने के लिए प्रिंट करता है। तो जो कुछ भी stuff
करने के लिए प्रिंट करने की कोशिश करता है, उसे कैप्चर किया जाता है, पास किया जाता है echo
और उसके द्वारा प्रिंटआउट किया जाता है echo
।
अगर आप का आउटपुट चाहिए stuff
को प्रिंटआउट में प्रिंट किया जाए, तो केवल एकमात्र चलाएं stuff
।
`…`
वाक्य रचना के रूप में ही उद्देश्य में कार्य करता $(…)
(एक ही नाम के तहत: "कमांड प्रतिस्थापन"), वहाँ तो आप आँख बंद करके उन्हें अदला-बदली नहीं कर सकते हैं, हालांकि कुछ अंतर हैं। यह FAQ देखें और यह प्रश्न ।
क्या मुझे echo $(stuff)
किसी भी चीज से बचना चाहिए ?
एक कारण है जिसका आप उपयोग करना चाह सकते हैं echo $(stuff)
यदि आप जानते हैं कि आप क्या कर रहे हैं, तो । echo $(stuff)
यदि आप वास्तव में नहीं जानते कि आपको क्या करना है, तो उसी कारण से आपको बचना चाहिए ।
बिंदु है stuff
और echo $(stuff)
बिल्कुल बराबर नहीं हैं। उत्तरार्द्ध का मतलब है stuff
कि डिफॉल्ट मान के साथ आउटपुट पर स्प्लिट + ग्लोब ऑपरेटर को कॉल करना$IFS
। कमांड प्रतिस्थापन का दोहराव इसे रोकता है। कमांड प्रतिस्थापन का एकल उद्धरण यह अब एक कमांड प्रतिस्थापन नहीं है।
यह देखने के लिए कि यह इन कमांड को विभाजित करने के लिए कब आता है:
echo "a b"
echo $(echo "a b")
echo "$(echo "a b")" # the shell is smart enough to identify the inner and outer quotes
echo '$(echo "a b")'
और ग्लोबिंग के लिए:
echo "/*"
echo $(echo "/*")
echo "$(echo "/*")" # the shell is smart enough to identify the inner and outer quotes
echo '$(echo "/*")'
जैसा कि आप देख सकते हैं echo "$(stuff)"
समकक्ष (-ish *) से हैstuff
। आप इसका उपयोग कर सकते हैं लेकिन इस तरह से चीजों को जटिल करने की क्या बात है?
दूसरी ओर यदि आप चाहते हैं कि उत्पादन stuff
विभाजन + ग्लोबिंग से गुजरता है तो आप पा सकते हैंecho $(stuff)
उपयोगी । हालांकि यह आपका सचेत निर्णय होना है।
आउटपुट उत्पन्न करने वाले कमांड हैं जिनका मूल्यांकन किया जाना चाहिए (जिसमें विभाजन, ग्लोबिंग और अधिक शामिल हैं) और शेल द्वारा चलाया जाता है, इसलिए eval "$(stuff)"
एक संभावना है ( इस उत्तर को देखें )। मैंने कभी ऐसा कमांड नहीं देखा है जिसे मुद्रित होने से पहले अतिरिक्त विभाजन + ग्लोबिंग से गुजरने के लिए इसके आउटपुट की आवश्यकता हो । जानबूझकर उपयोग करना echo $(stuff)
बहुत ही असामान्य लगता है।
व्हाट अबाउट var=$(stuff); echo "$var"
?
अच्छी बात। यह स्निपेट:
var=$(stuff)
echo "$var"
echo "$(stuff)"
समतुल्य (-ish *) के बराबर होना चाहिए stuff
। यदि यह पूरा कोड है, तो बस चलाएंstuff
इसके बजाय ।
यदि, हालांकि, आपको stuff
एक से अधिक बार इस दृष्टिकोण के आउटपुट का उपयोग करने की आवश्यकता है
var=$(stuff)
foo "$var"
bar "$var"
आमतौर पर से बेहतर है
foo "$(stuff)"
bar "$(stuff)"
यहां तक कि अगर foo
है echo
और आप प्राप्त echo "$var"
अपने कोड में, यह यह इस तरह से रखने के लिए बेहतर हो सकता है। विचार करने के लिए बातें:
var=$(stuff)
stuff
एक बार रन के साथ ; भले ही कमांड तेज हो, एक ही आउटपुट को दो बार गणना करने से बचना सही बात है। या शायद stuff
stdout को लिखने के अलावा (जैसे एक अस्थायी फ़ाइल बनाना, एक सेवा शुरू करना, एक वर्चुअल मशीन शुरू करना, एक दूरस्थ सर्वर को सूचित करना) के अलावा अन्य प्रभाव होते हैं, इसलिए आप इसे कई बार चलाना नहीं चाहते हैं।
- यदि आप
stuff
समय-आधारित या कुछ यादृच्छिक उत्पादन उत्पन्न करते हैं, तो आपको foo "$(stuff)"
और से असंगत परिणाम मिल सकते हैं bar "$(stuff)"
। var=$(stuff)
का मान $var
निश्चित होने के बाद और आप सुनिश्चित हो सकते हैं foo "$var"
और bar "$var"
समान कमांड लाइन तर्क प्राप्त कर सकते हैं ।
इसके बजाय कुछ मामलों में foo "$var"
आप (आवश्यकता) का उपयोग कर सकते हैं foo $var
, खासकर यदि आपके stuff
लिए कई तर्क उत्पन्न होते हैं foo
(एक सरणी चर बेहतर हो सकता है यदि आपका शेल इसका समर्थन करता है)। फिर से जानिए कि आप क्या कर रहे हैं। यह बात आती है echo
के बीच का अंतर echo $var
और echo "$var"
के बीच के समान ही है echo $(stuff)
और echo "$(stuff)"
।
* समतुल्य ( -इश) )?
मैंने कहा कि echo "$(stuff)"
(-ish) के बराबर है stuff
। कम से कम दो मुद्दे हैं जो इसे बिल्कुल समकक्ष नहीं बनाते हैं:
$(stuff)
stuff
एक उपधारा में चलाता है, इसलिए यह कहना बेहतर है कि echo "$(stuff)"
(-ish) के बराबर है (-इश) (stuff)
। कमांड जो शेल में चलते हैं, उन्हें प्रभावित करते हैं, यदि एक सबस्क्रिप्शन में, मुख्य शेल को प्रभावित नहीं करते हैं।
इस उदाहरण में stuff
है a=1; echo "$a"
:
a=0
echo "$(a=1; echo "$a")" # echo "$(stuff)"
echo "$a"
इससे तुलना कीजिए
a=0
a=1; echo "$a" # stuff
echo "$a"
और साथ
a=0
(a=1; echo "$a") # (stuff)
echo "$a"
एक अन्य उदाहरण के साथ शुरू stuff
किया जा रहा है cd /; pwd
:
cd /bin
echo "$(cd /; pwd)" # echo "$(stuff)"
pwd
और परीक्षण stuff
और (stuff)
संस्करण।
echo
अनियंत्रित डेटा प्रदर्शित करने के लिए एक अच्छा उपकरण नहीं है । यह echo "$var"
हम बात कर रहे थे जो होना चाहिए था printf '%s\n' "$var"
। लेकिन चूंकि प्रश्न का उल्लेख है echo
और चूंकि सबसे संभावित समाधान echo
पहली जगह में उपयोग नहीं करना है, इसलिए मैंने printf
अब तक लागू नहीं करने का फैसला किया ।
stuff
या (stuff)
stdout और stderr आउटपुट को इंटरलेय echo $(stuff)
करेगा , जबकि stuff
(जो पहले चलाता है) से सभी stderr आउटपुट प्रिंट करेगा , और उसके बाद ही stdout आउटपुट echo
(जो अंतिम चलता है) पचता है ।
$(…)
किसी भी अनुगामी newline से स्ट्रिप्स और फिर echo
इसे वापस जोड़ता है। इसलिए की echo "$(printf %s 'a')" | xxd
तुलना में अलग आउटपुट देता है printf %s 'a' | xxd
।
कुछ कमांड ( ls
उदाहरण के लिए) अलग-अलग तरीके से काम करते हैं, यह निर्भर करता है कि मानक आउटपुट कंसोल है या नहीं; ऐसा ls | cat
नहीं ls
करता है। इसी तरह echo $(ls)
से अलग तरह से काम करेगा ls
।
ls
एक तरफ रख दें, एक सामान्य मामले में अगर आपको इस दूसरे व्यवहार के लिए मजबूर करना है, तो इससे stuff | cat
बेहतर है echo $(ls)
या echo "$(ls)"
क्योंकि यह यहां वर्णित अन्य सभी मुद्दों को ट्रिगर नहीं करता है।
संभवतः अलग-अलग निकास स्थिति (इस विकी उत्तर की पूर्णता के लिए उल्लेख किया गया है; विवरण के लिए एक और उत्तर देखें जो क्रेडिट के योग्य है)।