शेल स्क्रिप्ट में $ {} और $ () के बीच अंतर


28
$ echo $(date)
Thu Jul 2 16:33:11 SGT 2015
$ echo ${date}

$ name=foo
$ echo $(name)
ksh: name:  not found

$ echo ${name}
foo

$ {चर} जैसा लगता है, वैसा ही $ चर भी है। जबकि $ () एक कमांड निष्पादित करना है। $ {} का उपयोग क्यों करें?


जवाबों:


39

$(command)"कमांड प्रतिस्थापन" है। जैसा कि आप समझते हैं, यह चलाता है command, इसके आउटपुट को पकड़ता है, और सम्मिलित करता है कमांड लाइन में जो इसमें शामिल है $(…); जैसे,

$ ls -ld $(date +%B).txt
-rwxr-xr-x  1 Noob Noob    867 Jul  2 11:09 July.txt

${parameter}"पैरामीटर प्रतिस्थापन" है। " पैरामीटर विस्तार " शीर्षक के तहत शेल के मैन पेज, बैश (1) में बहुत सारी जानकारी पाई जा सकती है :

${parameter}
    पैरामीटर का मान प्रतिस्थापित किया गया है। ब्रेस की आवश्यकता तब होती है जब पैरामीटर एक से अधिक अंकों के साथ एक स्थितीय पैरामीटर होता है, या जब पैरामीटर का अनुसरण एक चरित्र द्वारा किया जाता है जिसे इसके नाम के हिस्से के रूप में व्याख्या नहीं किया जाना है।

स्थितीय मापदंडों के लिए, नीचे " स्थितिगत पैरामीटर " देखें। इसके सबसे आम उपयोग में, जैसा कि अन्य उत्तरों में दिखाया गया है, parameterएक चर नाम है। ${…}प्रपत्र, जैसा कि ऊपर पैरा के अंत में कहा गया है, यदि आप एक चर के मूल्य (यानी, प्राप्त करने देता है ) और यह तुरंत पालन एक पत्र, अंक, या अंडरस्कोर के साथ:$variable_name

$ जानवर = बिल्ली
$ गूंज $ जानवर
                                # "जानवरों" के रूप में ऐसा कोई चर नहीं ।
$ गूंज $ {जानवर} है
बिल्ली की
$ गूंज $ animal_food
                                # "पशु_ खाद्य" जैसा कोई चर नहीं ।
$ गूंज $ {पशु} _फूड
बिल्ली का खाना

आप उद्धरणों के साथ भी ऐसा कर सकते हैं:

$ गूंज "$ जानवर"
बिल्ली की

या, विकल्पों में एक अभ्यास के रूप में, आप एक दूसरे चर का उपयोग कर सकते हैं:

$ बहुवचन = एस
$ गूंज $ जानवर $ बहुवचन
बिल्ली की

लेकिन यह सिर्फ चरण 1 है। मैन पेज में अगला पैराग्राफ दिलचस्प है, हालांकि थोड़ा गूढ़ है:

यदि पैरामीटर का पहला वर्ण एक विस्मयादिबोधक बिंदु ( !) है, तो चर अप्रत्यक्ष का एक स्तर पेश किया जाता है। बैश बाकी पैरामीटर से बने वेरिएबल के मान को वेरिएबल के नाम के रूप में इस्तेमाल करता है; इस चर का फिर विस्तार किया जाता है और उस मूल्य का उपयोग बाकी सबस्टेशन में किया जाता है, बजाय पैरामीटर के मूल्य के । इसे अप्रत्यक्ष विस्तार के रूप में जाना जाता है ।     ... (अपवाद) ...    विस्मयादिबोधक बिंदु को अप्रत्यक्ष रूप से पेश करने के लिए तुरंत बाएं ब्रेस का पालन करना चाहिए।

मुझे यकीन नहीं है कि मैं उदाहरण के अलावा इसे कैसे स्पष्ट कर सकता हूं:

$ जानवर = बिल्ली
$ गूंज $ जानवर
बिल्ली
$ बिल्ली = टैबी
$ गूंज $ बिल्ली
बद गप्पी
$ गूंज $ {! जानवर}
धारीदार                            # यदि $ जानवर है "बिल्ली" , तो $ {! पशु} है $ बिल्ली , यानी, "धारीदार"

तो चलिए उस चरण को 1½ कहते हैं। कई दिलचस्प चीजें हैं जो आप चरण 2 के रूप में कर सकते हैं:

$ जानवर = बिल्ली
$ गूंज $ {# जानवर}
3                                # स्ट्रिंग की लंबाई
$ गूंज $ {जानवर / पर / उल्लू}
गाय                              # प्रतिस्थापन

आप बिना उन चीजों से कोई भी कार्य नहीं कर सकता {... }ब्रेसिज़।

स्थितिगत पैरामीटर

इस कृत्रिम उदाहरण पर विचार करें :

$ बिल्ली myecho.sh
गूंज $ 1 $ 2 $ 3 $ 4 $ 5 $ 6 $ 7 $ 8 $ 9 $ 10 $ 11 $ 12 $ 13 $ 14 $ 15
$ ./myecho.sh हे डूडल डूडल, द कैट एंड फिडेल, गाय ने चंद्रमा पर छलांग लगाई।
हे डूडल डूडल, द कैट एंड द फिडल, द हेय हेय 1 हे 2 ए 3 हे 4 हे 5

क्योंकि खोल नहीं समझती $10, $11, आदि यह व्यवहार करता है $10जैसे कि वह थे ${1}0। लेकिन यह समझ में आता है ${10}, ${11}आदि, जैसा कि मैन पेज में उल्लेख किया गया है ("एक से अधिक अंकों के साथ एक स्थितीय पैरामीटर")।

लेकिन वास्तव में इस तरह की स्क्रिप्ट नहीं लिखते हैं; लंबी तर्क सूचियों से निपटने के बेहतर तरीके हैं।

ऊपर ( निर्माण के कई और रूपों के साथ ) शेल के मैन पेज, बैश (1) में अधिक लंबाई पर चर्चा की गई है ।${parameter…something_else}

उद्धरण पर एक नोट

ध्यान दें कि आपको हमेशा शेल वेरिएबल्स को उद्धृत करना चाहिए जब तक कि आपके पास एक अच्छा कारण नहीं है, और आपको यकीन है कि आप जानते हैं कि आप क्या कर रहे हैं। इसके विपरीत, जबकि ब्रेसिज़ महत्वपूर्ण हो सकते हैं, वे उद्धरण के रूप में महत्वपूर्ण नहीं हैं।

$ फ़ाइल नाम = "नर्सरी कविता"
$ ls -ld $ {फ़ाइल नाम}
ls: नर्सरी तक नहीं पहुँच सकते: ऐसी कोई फ़ाइल या निर्देशिका नहीं
ls: rhyme.txt तक नहीं पहुंच सकता: ऐसी कोई फ़ाइल या निर्देशिका नहीं
$ ls -ld "$ फ़ाइलनाम"
-rwxr-xr-x 1 Noob Noob 5309 Jul 2 11:09 नर्सरी कविता

यह भी स्थितीय मापदंडों (यानी, कमांड-लाइन तर्क; उदा। "$1") पर लागू होता है और कमांड प्रतिस्थापन भी:

$ ls -ld $ (दिनांक "+% B% Y")। txt
ls: जुलाई तक नहीं पहुंच सकता: ऐसी कोई फ़ाइल या निर्देशिका नहीं
ls: 2015 तक नहीं पहुंच सकता। Txt: ऐसी कोई फ़ाइल या निर्देशिका नहीं
$ ls -ld "$ (दिनांक" +% B% Y ")। txt"
-rwxr-xr-x 1 नोब नोब 687 जुलाई 2 11:09 जुलाई 2015.txt

देखें बैश उद्धरण उद्धरण और $(… के बीच की बातचीत पर एक संक्षिप्त ग्रंथ के लिए कमांड प्रतिस्थापन पर unescaped)


अद्भुत उदाहरण के लिए धन्यवाद। क्या आप इसका उपयोग विस्तृत कर सकते हैं! आपके उदाहरण में। मुझे वास्तव में समझ नहीं आया कि यह कैसे काम करता है।
नोब

@ नोब: ठीक है, मैंने इसके उपयोग पर विस्तार से बताया !
जी-मैन का कहना है कि 'मोनिका'

धन्यवाद। किसी तरह! जानवर वास्तव में मूल्य बिल्ली के बजाय चर बिल्ली का उल्लेख कर रहा है। क्या आप मुझे यह भी बता सकते हैं कि गूंज $ {जानवर / पर / उल्लू} में "ग" कैसे बनता है / किसी व्यक्ति को बैश के बारे में समझाता है ... मुझे नहीं पता। समझने केलिए कठिन।
नोब

इसके अलावा, क्या आप इस वाक्यांश को विस्तृत कर सकते हैं - "$ {पैरामीटर} पैरामीटर का मान प्रतिस्थापित है।" के साथ प्रतिस्थापित? अगर पैरामीटर फल है और इसका मूल्य सेब है - फल = सेब, तो $ {फल} - सेब को प्रतिस्थापित किया जाता है ?? वास्तव में यहाँ प्रतिस्थापित अर्थ नहीं मिलता है
Noob

@ नोब: " ${!animal}वास्तव $catमें मूल्य बिल्ली के बजाय चर का जिक्र है ।" हाँ, यह बिल्कुल यही बात है। "गूंज $ {जानवर / पर / उल्लू" में "ग" कैसे बनता है? / पर "ग" नहीं बनता है; "बिल्ली" तब "गाय" बन जाती है जब "पर" को "उल्लू" से बदल दिया जाता है।
जी-मैन का कहना है कि 'मोनिका'

7

आपके उदाहरण में, $ var और $ {var} समान हैं। हालाँकि, जब आप एक स्ट्रिंग में चर का विस्तार करना चाहते हैं, तो घुंघराले ब्रेस उपयोगी होते हैं:

    $ string=foo
    $ echo ${string}bar
      foobar
    $ echo $stringbar

    $ 

इस प्रकार घुंघराले ब्रेसिज़ नए चर का नाम प्राप्त करने के लिए चर को प्रतिस्थापित करने का एक साधन प्रदान करते हैं, जिसे स्वयं प्रतिस्थापित किया जाना है।


4

मैं आमतौर पर इसे और अधिक सामान्यतः तार में देखता हूं। कुछ इस तरह काम नहीं करेगा:

var="a"
echo "$varRAW_STRING"

लेकिन यह होगा:

var="a"
echo "${var}RAW_STRING"

जैसा कि आपने ठीक कहा, $()एक कमांड निष्पादित करने के लिए उपयोग किया जाता है:

dir_contents=$(ls)

आप बैकटिक्स का भी उपयोग कर सकते हैं, लेकिन मुझे $()अधिक बहुमुखी लगता है । एक बात के लिए, बैकटिक्स को आसानी से नहीं किया जा सकता है।

date_directory=`ls `date '+%Y-%m-%d'`` # Makes no sense
date_directory=$(ls $(date '+%Y-%m-%d')) # Much better

असल में, बैकटिक्स को नेस्टेड किया जा सकता है date_directory=`ls \`date '+%Y-%m-%d'\``:। लेकिन यह बहुत बदसूरत है; $(…)बहुत स्पष्ट और उपयोग करने में आसान है।
जी-मैन का कहना है कि 'मोनिका'

ठीक है पर्याप्त ठीक है। यह तकनीकी रूप से संभव है, लेकिन मैं किसी को कभी भी सिर्फ पठनीयता की वजह से ऐसा करने की कल्पना नहीं कर सकता
बाइट्स

1
ठीक है, `…`था साल के लिए (केवल) आदेश प्रतिस्थापन के लिए वाक्य रचना से पहले , आविष्कार किया गया था, ताकि आप कुछ भी कल्पना की जरूरत नहीं है - लोगों को यह किया था। $(…)
जी-मैन का कहना है कि 'मोनिका'

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