में इस सवाल का कोई एक समस्या एक का उपयोग कर रिपोर्ट यहाँ दस्तावेज़ के अंदर एक उद्धृत सीमांकक शब्द के साथ $(...)
आदेश प्रतिस्थापन , जहां एक बैकस्लैश \
दस्तावेज़ चलाता अंदर एक पंक्ति के अंत में नई पंक्ति-में शामिल होने लाइन निरंतरता , जबकि एक ही यहाँ दस्तावेज़ के बाहर की उम्मीद के रूप में आदेश प्रतिस्थापन काम करता है ।
यहाँ एक सरल उदाहरण दस्तावेज़ है:
cat <<'EOT'
abc ` def
ghi \
jkl
EOT
इसमें एक पंक्ति के अंत में एक बैकटिक और एक बैकस्लैश शामिल है। परिसीमन को उद्धृत किया जाता है, इसलिए शरीर के अंदर कोई विस्तार नहीं होता है। सभी बॉर्न-बाइक में मैं इस सामग्री को शब्दशः आउटपुट कर सकता हूं। अगर मैं कमांड डॉक्यूमेंट के अंदर समान डॉक्यूमेंट डालता हूं:
x=$(cat <<'EOT'
abc ` def
ghi \
jkl
EOT
)
echo "$x"
तब वे पहचान के लिए व्यवहार नहीं करते हैं:
dash
,ash
,zsh
,ksh93
, बिजीबॉक्सash
,mksh
और SunOS 5.10 POSIXsh
सभी दस्तावेज़ के शब्दशः सामग्री, पहले की तरह दे।- बैश 3.2 एक बेजोड़ बैकटिक के लिए एक सिंटैक्स त्रुटि देता है। मिलान किए गए बैकटिक्स के साथ, यह सामग्री को कमांड के रूप में चलाने का प्रयास करता है।
- बैश 4.3 एक ही लाइन पर "ghi" और "jkl" का पतन करता है, लेकिन इसमें कोई त्रुटि नहीं है।
--posix
विकल्प यह प्रभावित नहीं करता। कुसलानंद मुझसे कहता है (धन्यवाद!)pdksh
वही व्यवहार करता है ।
मूल प्रश्न में, मैंने कहा कि यह बैश के पार्सर में एक बग था। क्या यह? [अद्यतन: हाँ ] POSIX से प्रासंगिक पाठ (शेल कमांड भाषा की सभी परिभाषा) जो मुझे मिल सकती है:
- Itution2.6.3 कमांड प्रतिस्थापन :
$ (कमांड) फॉर्म के साथ, ओपन कोष्ठक के मिलान समापन कोष्ठक के बाद सभी वर्ण कमांड का गठन करते हैं। किसी भी मान्य शेल स्क्रिप्ट का उपयोग कमांड के लिए किया जा सकता है , केवल एक स्क्रिप्ट को छोड़कर जिसमें अप्रत्यक्ष परिणाम होते हैं।
- §2.7.4 यहाँ-दस्तावेज़ :
यदि शब्द के किसी भाग को उद्धृत किया जाता है, तो शब्द पर उद्धरण हटाने का प्रदर्शन करके परिसीमन का गठन किया जाएगा , और यहां-दस्तावेज़ लाइनों का विस्तार नहीं किया जाएगा।
- (2.2.1 पलायन चरित्र (बैकस्लैश) :
यदि एक <newline> <backslash> का अनुसरण करता है, तो शेल इसे लाइन निरंतरता के रूप में व्याख्या करेगा। इनपुट को टोकन में विभाजित करने से पहले <backslash> और <newline> को हटा दिया जाएगा।
- §2.3 टोकन मान्यता :
जब व्याकरण द्वारा एक io_here टोकन को मान्यता दी गई है ( शैल व्याकरण देखें ), अगले NEWLINE टोकन के तुरंत बाद एक या एक से अधिक लाइनें एक या अधिक दस्तावेजों के शरीर का निर्माण करती हैं और यहां के नियमों के अनुसार पार्स की जाएंगी- दस्तावेज़ ।
जब यह एक io_here को संसाधित नहीं कर रहा है , तो शेल अपने इनपुट में अगले वर्ण के नीचे पहला लागू नियम लागू करके अपने इनपुट को टोकन में तोड़ देगा। ...
...
- यदि वर्तमान वर्ण <backslash>, एकल-उद्धरण या डबल-उद्धरण है और इसे उद्धृत नहीं किया गया है, तो यह उद्धृत पाठ के अंत तक के बाद के वर्णों को उद्धृत करने को प्रभावित करेगा। के हवाले करने के लिए नियम के रूप में वर्णित हैं का हवाला देते हुए । टोकन मान्यता के दौरान कोई प्रतिस्थापन वास्तव में नहीं किया जाएगा, और परिणाम टोकन में बिल्कुल वर्ण शामिल होंगे जो इनपुट में दिखाई देंगे (<newline> में शामिल होने के अलावा), बिना किसी एम्बेडेड या संलग्न उद्धरण या प्रतिस्थापन ऑपरेटरों सहित अनमॉडिफाइड, और अंत के बीच। उद्धृत पाठ का।
इसकी मेरी व्याख्या यह है कि $(
समाप्ति के बाद तक के सभी वर्ण )
शैल लिपि, शब्दशः; यहाँ एक दस्तावेज़ प्रकट होता है, इसलिए यहाँ दस्तावेज़ सामान्य टोकन के बजाय प्रसंस्करण होता है; यहाँ दस्तावेज़ में एक उद्धृत परिसीमा है, जिसका अर्थ है कि इसकी सामग्री संसाधित वर्बटीम है; और भागने का चरित्र इसमें कभी नहीं आता है। मैं एक तर्क देख सकता हूं, हालांकि, यह मामला केवल संबोधित नहीं है, और दोनों व्यवहार स्वीकार्य हैं। यह संभव है कि मैंने कुछ प्रासंगिक पाठ को छोड़ दिया है।
- क्या यह स्थिति कहीं और स्पष्ट हो गई है?
- एक पोर्टेबल स्क्रिप्ट पर (सिद्धांत में) भरोसा करने में सक्षम होना चाहिए?
- क्या विशिष्ट उपचार इनमें से किसी भी गोले द्वारा किया जाता है (बैश 3.2 / बैश 4.3 / अन्य सभी) मानक द्वारा अनिवार्य है? मना किया हुआ? अनुमति है?
echo "$x"
, लेकिन चर के निरीक्षण के किसी भी तरीके से काम करता है। मैंने उस पंक्ति को नीचे में संपादित किया है।
$(...)
जो कुछ भी आउटपुट होता है, उसकी जगह ले लेता है ... अब, जब आपके उदाहरण में कमांड को सब्स्क्रिप्शन (इन bash
) में चलाते हैं तो यह अपेक्षित परिणाम को आउटपुट करता है। यह केवल तब होता है जब इसे कमांड प्रतिस्थापन में बदल दिया जाता है, जिससे यह "घी" और "जेकेएल" गिर जाता है। तो यह एक बग imo है