शब्द विभाजन क्या है? शेल प्रोग्रामिंग में क्यों महत्वपूर्ण है?


16

मैं उस भूमिका शब्द को लेकर भ्रमित हो रहा हूं, जिसमें बंटवारे में भूमिका निभाई जाती है zsh। सी, पायथन या MATLAB में प्रोग्रामिंग करते समय मुझे इस अवधारणा से अवगत नहीं कराया गया है, और इसने मेरी रुचि को बढ़ा दिया है कि शब्द विभाजन क्यों शेल प्रोग्रामिंग के लिए कुछ विशिष्ट लगता है।

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

यहाँ मेरी उलझन का एक उदाहरण है zsh:

में जेड शैल पूछे जाने वाले प्रश्न , मैं निम्नलिखित पढ़ें:

३.१: $varजहाँ var="foo bar"मुझे उम्मीद नहीं है वहाँ क्यों नहीं करता है?

अधिकांश बॉर्न-शेल डेरिवेटिव में, एकाधिक-शब्द चर जैसे कि var="foo bar" एक कमांड में पारित होने या for foo in $varलूप में उपयोग किए जाने पर शब्दों में विभाजित होते हैं । डिफ़ॉल्ट रूप से, zsh में वह व्यवहार नहीं होता है: चर बरकरार रहता है। (यह एक बग नहीं है! नीचे देखें!) SH_WORD_SPLITसंगतता प्रदान करने के लिए विकल्प मौजूद है।

हालाँकि, Z शेल मैनुअल में , मैंने निम्नलिखित पढ़ा:

SH_WORD_SPLIT (-y) <K> <S>

अनियोजित पैरामीटर विस्तार पर प्रदर्शन करने के लिए क्षेत्र विभाजन का कारण बनता है। ध्यान दें कि इस विकल्प का शब्द विभाजन से कोई लेना-देना नहीं है । (पैरामीटर विस्तार देखें।)

यह क्यों कहता है कि करता SH_WORD_SPLITहै कोई लेना देना नहीं शब्द बंटवारे के साथ? क्या शब्द विभाजन ठीक नहीं है कि यह सब क्या है?

जवाबों:


22

प्रारंभिक गोले में केवल एक ही डेटा प्रकार था: तार। लेकिन स्ट्रिंग की सूचियों में हेरफेर करना आम बात है, आमतौर पर जब एक कार्यक्रम के लिए कई फ़ाइल नाम तर्क के रूप में पास किए जाते हैं। बंटवारे के लिए एक अन्य सामान्य उपयोग का मामला है जब एक कमांड परिणाम की सूची को आउटपुट करता है: कमांड का आउटपुट एक स्ट्रिंग है, लेकिन वांछित डेटा स्ट्रिंग की एक सूची है। किसी चर में फ़ाइल नामों की सूची संग्रहीत करने के लिए, आप उनके बीच रिक्त स्थान डालेंगे। फिर इस तरह एक शेल स्क्रिप्ट

files="foo bar qux"
myprogram $files

myprogramतीन तर्कों के साथ बुलाया जाता है, क्योंकि शेल स्ट्रिंग $filesको शब्दों में विभाजित करता है । उस समय, फ़ाइल नामों में रिक्त स्थान को या तो निषिद्ध किया गया था या व्यापक रूप से नॉट डन माना गया था।

कॉर्न खोल शुरू की सरणियों: यदि आप एक चर में तार की एक सूची संग्रहीत कर सकता है। कोर्न शेल तत्कालीन स्थापित बॉर्न शेल के साथ संगत था, इसलिए नंगे चर विस्तार शब्द विभाजन के दौर से गुजर रहे थे, और सरणियों का उपयोग करके कुछ सिंटैक्टिक ओवरहेड की आवश्यकता थी। आप ऊपर स्निपेट लिखेंगे

files=(foo bar qux)
myprogram "${files[@]}"

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

files=(foo bar qux)
myprogram $files

इन दिनों, फ़ाइल नामों में रिक्तियाँ कुछ ऐसी हैं जिनसे आपको सामना करने की आवश्यकता है, क्योंकि दोनों ही उपयोगकर्ता उनसे काम करने की अपेक्षा करते हैं और क्योंकि कई स्क्रिप्ट्स को सुरक्षा-संवेदनशील संदर्भों में निष्पादित किया जाता है, जहाँ एक हमलावर फ़ाइल नामों के नियंत्रण में हो सकता है। इसलिए स्वचालित शब्द विभाजन अक्सर एक उपद्रव है; इसलिए मेरी सामान्य सलाह है कि हमेशा दोहरे उद्धरण चिह्नों का उपयोग करें "$foo", जब तक आप यह न समझें कि आपको किसी विशेष उपयोग के मामले में शब्द विभाजन की आवश्यकता क्यों है। (ध्यान दें कि नंगे चर विस्तार ग्लोबिंग से भी गुजरते हैं।)


धन्यवाद गिल्स, यह वास्तव में उपयोगी है! क्या यह कहना सही है कि मोटे तौर पर शब्द का विभाजन रूप के तारों को रूप की "word1 word2 word3"सूची / सरणियों में परिवर्तित करता है "word1" "word2" "word3"? मैंने ओपी को zsh में भ्रम के एक विशिष्ट स्रोत के साथ अद्यतन किया है।
एमिलियो वाज़केज़-रीना

1
@intrpc "वर्ड स्प्लिटिंग" प्राकृतिक भाषा के शब्दों पर नहीं बल्कि $IFSपात्रों पर विभाजित है । 4. "क्षेत्र विभाजन" एक बेहतर नाम है। लेकिन शेल शब्द में इस अवधारणा के लिए अक्सर "शब्द विभाजन" का उपयोग किया जाता है। Zsh डॉक्यूमेंटेशन शब्दों पर आधारित है।
गिल्स एसओ- बुराई को रोकना '

1
rcजब चर और सरणियों की बात आती है तो zsh की तुलना में एक बेहतर डिज़ाइन के लिए यह भी देखें (plan9 खोल, यूनिक्स में भी पोर्ट किया गया)।
स्टीफन चेज़ेलस

3

शब्द विभाजन वास्तव में खोल विशिष्ट नहीं है।

पाठ इनपुट को पार्स करने की आवश्यकता वाले अधिकांश प्रोग्राम पहले चरण के रूप में शब्द विभाजन के कुछ रूप का उपयोग करते हैं। यह इन "शब्दों", संख्याओं, संचालकों, तार, टोकन और जो भी समान संस्थाओं को संसाधित करने की आवश्यकता है, उनकी पहचान करने से पहले किया जाता है।

गोले के साथ जो विशिष्ट है वह यह है कि उन्हें सही ढंग से कमांड की तर्क सूची (सी argc / argv, python sys.argv) का निर्माण करना है, जिसमें एम्बेडेड स्पेस, खाली तर्क, कस्टम सीमांकक और इतने पर तर्क पारित करना शामिल है। कई गोले कुछ लचीलेपन की अनुमति देने के लिए IFS चर का उपयोग करते हैं।


3

ज़श के इस विशिष्ट मामले में शब्द विभाजन को क्षेत्र विभाजन से थोड़ा अलग रूप में परिभाषित किया गया है।

गौर कीजिए prog a b c, यह तीन तर्कों में बीत जाएगा, चाहे आप कैसे भी सेट करें IFS। ये है शब्द विभाजन है।

यदि आप करते हैं A="a b c"; prog $A, तो यह तीन तर्कों में पारित होगा यदि IFSअंतरिक्ष या एक तर्क शामिल हैं अन्यथा। यह फील्ड स्प्लिटिंग है।

यहां परिभाषाएं सूक्ष्म हैं। Zsh दस्तावेज़ जो कहना चाह रहा है, वह यह है कि, भले ही आप उस विकल्प को अक्षम कर दें, फिर भी आपको prog a b cअलग-अलग तर्क मिलेंगे (जो कि लोग उनसे अपेक्षा करते हैं)।


1
एक लंबे समय तक zsh डेवलपर बार्ट शेफ़र ने पुष्टि की कि यह वास्तव में उस पाठ का अभिप्राय है
स्टीफन चेज़लस
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.