बैश (जोड़े गए) में दोहरे उद्धरण चिह्न कैसे हैं?


15

मै इस्तेमाल कर रहा हूँ GNU bash 4.3.48 । निम्नलिखित दो आदेशों पर विचार करें जो केवल एक डॉलर के संकेत से भिन्न होते हैं।

कमांड 1:

echo "(echo " * ")"

कमांड 2:

echo "$(echo " * ")"

उनमें से आउटपुट क्रमशः हैं

(echo  test.txt ppcg.sh )

तथा

 * 

तो जाहिर है पहले मामले में * ग्लोबेड है, जिसका अर्थ है कि पहला उद्धरण चिह्न दूसरे के साथ एक जोड़ी बनाने के लिए जाता है, और तीसरा और चौथा एक और जोड़ी बनाता है।

दूसरे मामले में * ग्लोब नहीं है, और आउटपुट में बिल्कुल दो अतिरिक्त स्थान हैं, एक तारांकन से पहले और एक बाद, जिसका अर्थ है कि दूसरा उद्धरण चिह्न तीसरे के साथ जाता है, और पहला चौथे के साथ जाता है।

क्या $()निर्माण के अलावा कोई अन्य मामले हैं जो कोटेशन के निशान अगले एक के साथ मेल नहीं खाते हैं, लेकिन इसके बजाय नेस्टेड हैं? क्या यह व्यवहार अच्छी तरह से प्रलेखित है और यदि हां, तो मैं इसके अनुरूप दस्तावेज कहां से प्राप्त कर सकता हूं?



एक बार फिर, यूएल एसई में वाक्य रचना हाइलाइट गलत और भ्रामक है, हालांकि जेएस को दोष देने वाला एक है।
वीजुन झोउ

जवाबों:


14

किसी भी घोंसले के निर्माण जो स्ट्रिंग्स के अंदर प्रक्षेपित किए जा सकते हैं, उनके अंदर आगे के तार हो सकते हैं: उन्हें एक नई स्क्रिप्ट की तरह पार्स किया जाता है, समापन मार्कर तक, और यहां तक ​​कि कई स्तरों को नेस्टेड किया जा सकता है। सभी बार उनमें से एक के साथ शुरू होता है$ । उन सभी को बैश मैनुअल और पोसिक्स शेल कमांड लैंग्वेज स्पेसिफिकेशन के संयोजन में प्रलेखित किया गया है।

इन निर्माणों के कुछ मामले हैं:

  • आदेश प्रतिस्थापन$( ... ) , जैसा कि आपने पाया है। POSIX इस व्यवहार को निर्दिष्ट करता है :

    $(command)फ़ॉर्म के साथ , खुले कोष्ठक के मिलान समापन कोष्ठक के बाद सभी वर्ण कमांड का गठन करते हैं। किसी भी मान्य शेल स्क्रिप्ट का उपयोग कमांड के लिए किया जा सकता है ...

    उद्धरण मान्य शेल स्क्रिप्ट का हिस्सा हैं, इसलिए उन्हें अपने सामान्य अर्थ के साथ अनुमति दी जाती है।

  • कमांड प्रतिस्थापन का उपयोग कर `, भी।
  • उन्नत पैरामीटर प्रतिस्थापन प्रतिस्थापन के${parameter:-word} "शब्द" तत्व जैसे"शब्द" की परिभाषा है :

    खोल द्वारा एक इकाई के रूप में व्यवहार किए गए वर्णों का एक क्रम

    - जिसमें पाठ और यहां तक ​​कि मिश्रित उद्धरण शामिल हैं a"b"c'd'e- हालांकि विस्तार का वास्तविक व्यवहार उससे थोड़ा अधिक उदार है, और उदाहरण के लिए ${x:-hello world}काम भी करता है।

  • अंकगणित के साथ विस्तार$(( ... )) , हालांकि यह काफी हद तक बेकार है (लेकिन आप कमांड प्रतिस्थापन या चर विस्तार को भी घोंसला कर सकते हैं, और फिर उन के अंदर उपयोगी उद्धरण हैं)। POSIX में कहा गया है कि :

    अभिव्यक्ति को ऐसे माना जाएगा जैसे कि वह दोहरे-उद्धरणों में थी, सिवाय इसके कि अभिव्यक्ति के अंदर एक डबल-कोट विशेष रूप से व्यवहार नहीं किया गया है। शेल पैरामीटर विस्तार, कमांड प्रतिस्थापन और उद्धरण हटाने के लिए अभिव्यक्ति में सभी टोकन का विस्तार करेगा।

    तो यह व्यवहार स्पष्ट रूप से आवश्यक है। इसका मतलब echo "abc $((4 "*" 5))"है कि गोलाबारी के बजाय अंकगणित करता है।

    ध्यान दें कि पुरानी शैली के $[ ... ]अंकगणितीय विस्तार का उसी तरह व्यवहार नहीं किया जाता है: उद्धरण एक त्रुटि होगी यदि वे दिखाई देते हैं, भले ही विस्तार उद्धृत हो या न हो। यह फ़ॉर्म किसी भी अधिक पर प्रलेखित नहीं है, और इसका उपयोग वैसे भी करने के लिए नहीं है।

  • स्थानीय-विशिष्ट अनुवाद$"..." , जो वास्तव "में एक मूल तत्व के रूप में उपयोग करता है । $"एक इकाई के रूप में माना जाता है।

एक और घोंसले के शिकार का मामला है जिसकी आप उम्मीद नहीं कर सकते हैं, उद्धरण शामिल नहीं है, जो ब्रेस विस्तार के साथ है : {a,b{c,d},e}"एक ई.पू. ई" तक फैलता है। ${x:-a{b,c}d}करता नहीं घोंसला हालांकि,; इसे " a{b,c" के बाद एक पैरामीटर प्रतिस्थापन के रूप में माना जाता है d}। यह भी प्रलेखित है :

जब ब्रेसिज़ का उपयोग किया जाता है, तो मिलान समाप्त होने वाला ब्रेस पहले '}' 'बैकस्लैश या एक उद्धृत स्ट्रिंग के भीतर नहीं होता है, और एक एम्बेडेड अंकगणितीय विस्तार, कमांड प्रतिस्थापन, या पैरामीटर विस्तार के भीतर नहीं होता है।


एक सामान्य नियम के रूप में, सभी सीमांकित निर्माण उनके शरीर को आसपास के संदर्भ से स्वतंत्र रूप से पार्स करते हैं (और अपवाद को कीड़े के रूप में माना जाता है )। संक्षेप में, $(कमांड-प्रतिस्थापन कोड को देखने पर बस पार्सर को यह उपभोग करने के लिए कहता है कि वह शरीर से क्या खा सकता है, हालांकि यह एक नया कार्यक्रम है, और फिर जाँचता है कि उप-पार्सर के चलने के बाद अपेक्षित समाप्ति मार्कर (एक unescaped )या ))या }) प्रकट होता है चीजों से बाहर यह उपभोग कर सकते हैं।

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

आप इन निर्माणों के माध्यम से जितनी गहराई से उद्धृत कर सकते हैं, घोंसला बना सकते हैं और यह अपेक्षित रूप से काम करेगा। कहीं बीच में कोई उद्धरण देखकर भ्रमित हो जाएगा; इसके बजाय, वह आंतरिक संदर्भ में एक नए उद्धृत स्ट्रिंग की शुरुआत होगी।


धन्यवाद। में "blah/blah\n$(cat "${tmpdir}/${filename}.jpdf")", दूसरे दोहरे उद्धरण में पहले दोहरे उद्धरण का अंत क्यों नहीं है (जैसा कि आपके उत्तर में वाक्य रचना हाइलाइटिंग द्वारा दिखाया गया है), लेकिन अंदर एक स्ट्रिंग की शुरुआत $(...)? क्या इसलिए कि नीचे-ऊपर के बजाय बैश का पार्सर टॉप-डाउन है?
टिम

2
वहाँ की हैंडलिंग में भिन्नता का एक बहुत है "${var-"foo"}"( echo "${-+"*"}"के रूप में ही है echo *बॉर्न या उदाहरण के लिए कॉर्न खोल में) और व्यवहार मानक के अगले संस्करण में स्पष्ट रूप से अनिर्दिष्ट किया जाएगामेल-archive.com/austin-group-l@opengroup.org/msg00167.html
स्टीफन चेज़लस

3

शायद printf(इसके बजाय echo) दो उदाहरणों को देखने से मदद मिलेगी:

$ printf '<%s> ' "(echo " * ")"; echo
<(echo > <test.txt> <ppcg.sh> <file1> <file2> <file3> <)>

यह प्रिंट करता है (echo (पहला शब्द, जिसमें अनुगामी स्थान शामिल है), कुछ फाइलें और समापन शब्द )
कोष्ठक उद्धृत भाग का एक हिस्सा है (echo 
तारांकन (अब दो डबल कोट्स के रूप में अनक्चुलेटेड हैं) युग्मित फाइल की सूची में एक ग्लोब के रूप में विस्तारित किया जाता है।
और फिर, समापन कोष्ठक।

हालाँकि, आपका दूसरा कमांड निम्नानुसार काम करता है:

$ printf '<%s> ' "$(echo " * ")" ; echo
< * >

$एक कमांड प्रतिस्थापन शुरू होता है। यह एक नए सिरे से उद्धरण की शुरुआत करता है।
तारांकन उद्धृत किया गया है " * "और यही वह आदेश है (यहां यह एक कमांड है और उद्धृत स्ट्रिंग नहीं है) echoआउटपुट। अंत में, printfपुन: प्रारूपित करता है *और इसे प्रिंट करता है < * >

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