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एक बार रन के साथ ; भले ही कमांड तेज हो, एक ही आउटपुट को दो बार गणना करने से बचना सही बात है। या शायद stuffstdout को लिखने के अलावा (जैसे एक अस्थायी फ़ाइल बनाना, एक सेवा शुरू करना, एक वर्चुअल मशीन शुरू करना, एक दूरस्थ सर्वर को सूचित करना) के अलावा अन्य प्रभाव होते हैं, इसलिए आप इसे कई बार चलाना नहीं चाहते हैं।
- यदि आप
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)"क्योंकि यह यहां वर्णित अन्य सभी मुद्दों को ट्रिगर नहीं करता है।
संभवतः अलग-अलग निकास स्थिति (इस विकी उत्तर की पूर्णता के लिए उल्लेख किया गया है; विवरण के लिए एक और उत्तर देखें जो क्रेडिट के योग्य है)।