कमांड प्रतिस्थापन के अंदर यहां दस्तावेजों के हवाले से POSIX की क्या आवश्यकता है?


20

में इस सवाल का कोई एक समस्या एक का उपयोग कर रिपोर्ट यहाँ दस्तावेज़ के अंदर एक उद्धृत सीमांकक शब्द के साथ $(...)आदेश प्रतिस्थापन , जहां एक बैकस्लैश \दस्तावेज़ चलाता अंदर एक पंक्ति के अंत में नई पंक्ति-में शामिल होने लाइन निरंतरता , जबकि एक ही यहाँ दस्तावेज़ के बाहर की उम्मीद के रूप में आदेश प्रतिस्थापन काम करता है ।

यहाँ एक सरल उदाहरण दस्तावेज़ है:

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 POSIX shसभी दस्तावेज़ के शब्दशः सामग्री, पहले की तरह दे।
  • बैश 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 को संसाधित नहीं कर रहा है , तो शेल अपने इनपुट में अगले वर्ण के नीचे पहला लागू नियम लागू करके अपने इनपुट को टोकन में तोड़ देगा। ...

    ...

    1. यदि वर्तमान वर्ण <backslash>, एकल-उद्धरण या डबल-उद्धरण है और इसे उद्धृत नहीं किया गया है, तो यह उद्धृत पाठ के अंत तक के बाद के वर्णों को उद्धृत करने को प्रभावित करेगा। के हवाले करने के लिए नियम के रूप में वर्णित हैं का हवाला देते हुए । टोकन मान्यता के दौरान कोई प्रतिस्थापन वास्तव में नहीं किया जाएगा, और परिणाम टोकन में बिल्कुल वर्ण शामिल होंगे जो इनपुट में दिखाई देंगे (<newline> में शामिल होने के अलावा), बिना किसी एम्बेडेड या संलग्न उद्धरण या प्रतिस्थापन ऑपरेटरों सहित अनमॉडिफाइड, और अंत के बीच। उद्धृत पाठ का।

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


  • क्या यह स्थिति कहीं और स्पष्ट हो गई है?
  • एक पोर्टेबल स्क्रिप्ट पर (सिद्धांत में) भरोसा करने में सक्षम होना चाहिए?
  • क्या विशिष्ट उपचार इनमें से किसी भी गोले द्वारा किया जाता है (बैश 3.2 / बैश 4.3 / अन्य सभी) मानक द्वारा अनिवार्य है? मना किया हुआ? अनुमति है?

क्या आप हमें दिखा सकते हैं कि आप दूसरे मामले में अपना उत्पादन कैसे करते हैं?
जूली पेलेटियर

@JuliePelletier echo "$x", लेकिन चर के निरीक्षण के किसी भी तरीके से काम करता है। मैंने उस पंक्ति को नीचे में संपादित किया है।
माइकल होमर

2
लगता है यह एक आसान तय है। यह पैच कम से कम काम करने लगता है: ign_quoted_newline_in_quoted_heredoc.patch
geirha

1
मुझे लगता है कि आप इसे सही ढंग से व्याख्या कर रहे हैं और मानक बहुत स्पष्ट है क्योंकि "शेल कमांड सबस्टेशन का विस्तार उप-परिवेश में कमांड निष्पादित करके करेगा [...] और कमांड प्रतिस्थापन की जगह [...] के मानक आउटपुट के साथ। कमांड [...] " तो यह कमांड को सबशेल में चलाता है और $(...)जो कुछ भी आउटपुट होता है, उसकी जगह ले लेता है ... अब, जब आपके उदाहरण में कमांड को सब्स्क्रिप्शन (इन bash) में चलाते हैं तो यह अपेक्षित परिणाम को आउटपुट करता है। यह केवल तब होता है जब इसे कमांड प्रतिस्थापन में बदल दिया जाता है, जिससे यह "घी" और "जेकेएल" गिर जाता है। तो यह एक बग imo है
don_crissti

2
@ नागिरि I ने बैश बग की सूचना दी ; मैं pdksh के बारे में परेशान नहीं करने जा रहा हूँ क्योंकि यह वर्तमान रखरखाव की छाया भी नहीं लगता है।
माइकल होमर

जवाबों:


5

यह बैश की मेलिंग सूची पर पूछा गया था, और अनुरक्षक ने पुष्टि की कि यह एक बग था

उन्होंने यह भी उल्लेख किया कि POSIX में पाठ "अस्पष्ट नहीं है, लेकिन इसके लिए करीबी पढ़ने की आवश्यकता है।", इसलिए मैंने उस पर स्पष्टीकरण मांगा। इस मुद्दे का वर्णन और मानक की व्याख्या सहित उनका जवाब इस प्रकार था:

कमांड प्रतिस्थापन एक लाल हेरिंग है; यह केवल उसी में प्रासंगिक है जो यह बताता है कि बग कहाँ था।

यहाँ दस्तावेज़ में परिसीमन उद्धृत किया गया है, इसलिए लाइनों का विस्तार नहीं किया गया है। इस मामले में, शेल इनपुट से लाइनों को पढ़ता है जैसे कि वे उद्धृत किए गए थे। यदि एक बैकस्लैश एक संदर्भ में प्रकट होता है, जहाँ इसे उद्धृत किया जाता है, तो यह पलायन चरित्र (नीचे देखें) के रूप में कार्य नहीं करता है, और बैकस्लैश-न्यूलाइन की विशेष हैंडलिंग नहीं होती है। वास्तव में, यदि सीमांकक के किसी भी भाग को उद्धृत किया जाता है, तो यहां दस्तावेज़ की पंक्तियों को एकल-उद्धरण के रूप में पढ़ा जाता है।

Posix 2.2.1 में पाठ अजीब तरह से लिखा गया है, लेकिन इसका मतलब है कि बैकस्लैश केवल विशेष रूप से व्यवहार किया जाता है जब इसे उद्धृत नहीं किया जाता है। आप एक बैकस्लैश को उद्धृत कर सकते हैं और केवल एक उद्धरण या किसी अन्य बैकलैश के साथ सभी विस्तार को रोक सकते हैं।

करीबी पढ़ने वाला भाग एकल उद्धरणों को लागू करने वाला "विस्तारित नहीं" पाठ है। मानक 2.2 में कहता है कि यहां दस्तावेज़ "उद्धृत करने का दूसरा रूप" हैं, लेकिन उद्धृत करने का एकमात्र रूप जिसमें शब्दों का विस्तार नहीं किया गया है, वह एकल उद्धरण है। तो यह उद्धरण का एक रूप है जो कि लगभग सिंगल कोट्स की तरह है, लेकिन सिंगल कोट्स के समान नहीं है।


@ सच (1) मेरा मानना ​​है कि यह सभी सवालों का जवाब देता है और कुछ भी अतिश्योक्तिपूर्ण नहीं है। जवाब से शुरू होने वाली मेरी टिप्पणी एक मॉडरेटर द्वारा किए गए विलोपन के बारे में है, जिसने स्थिति को गलत समझा। (२) मेरी पर्याप्त प्रतिष्ठा नहीं है। (३) मैंने अपने उत्तरों को हटाने वाले लोगों के समान व्यवहार की सराहना की होगी, लेकिन मैं भविष्य में इसे ध्यान में रखूंगा। विचारों के लिए धन्यवाद।
केविन

मेरा कहना यह था कि आपके पहले पैराग्राफ में माइकल मोर्ज़ेक के साथ बातचीत है और सवाल का जवाब नहीं है। मुझे एहसास है कि किसी भी पोस्ट पर टिप्पणी करने के लिए आपके पास पर्याप्त प्रतिष्ठा नहीं है, लेकिन मेरा मानना ​​है कि आपके पास मेटा और चैट के लिए पर्याप्त है।
स्कॉट

1
@ देखें मैं समझता हूं और सराहना करता हूं कि आप उत्तर को सुव्यवस्थित करने की कोशिश कर रहे हैं, लेकिन मैंने उस सुव्यवस्थित उत्तर को पहले ही पोस्ट कर दिया (बस उद्धरण और इसके लिए एक लिंक), और यह कहा गया मॉडरेटर द्वारा किसी भी चर्चा के बिना हटा दिया गया था! और मैं उस पोस्ट को हटाने और विवाद करने के लिए हटाए गए पोस्ट में कोई लिंक नहीं देखें। मुझे उम्मीद थी कि उनकी निराधार आलोचना का जवाब देने से, यह नष्ट होने से बच जाएगा, पूछने वाले द्वारा स्वीकार किया जाएगा और फिर मैं प्रस्ताव को हटाने के लिए उत्तर को संशोधित करूंगा।
केविन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.