बैश में नेस्ट ब्रेस विस्तार रहस्य


19

इस:

$ echo {{a..c},{1..3}}

इसका उत्पादन करता है:

a b c 1 2 3

जो अच्छा है, लेकिन यह दिया जाना कठिन है

$ echo {a..c},{1..3}

देता है

a,1 a,2 a,3 b,1 b,2 b,3 c,1 c,2 c,3

क्या यह कहीं दस्तावेज है? बैश संदर्भ में यह उल्लेख नहीं है (भले ही यह इसे का उपयोग एक उदाहरण है)।

जवाबों:


18

खैर, यह एक समय में एक परत को खोलना है:

X{{a..c},{1..3}}Y

करने के लिए विस्तार किया जा रहा के रूप में दर्ज है X{a..c}Y X{1..3}Y(कि के X{A,B}Yलिए विस्तार किया XA XBसाथ Aकिया जा रहा है {a..c}और Bकिया जा रहा है {1..3}), खुद को विस्तार किया जा रहा के रूप में दस्तावेज XaY XbY XcY X1Y X2Y X3Y

दस्तावेज़ीकरण के लायक क्या हो सकता है कि वे नेस्टेड हो सकते हैं ( उदाहरण के लिए पहले वहाँ पहले बंद} नहीं होता है )।{

मुझे लगता है कि गोले पहले आंतरिक ब्रेसिज़ को हल करने के लिए चुना जा सकता था , जैसे कि }बारी में प्रत्येक समापन पर अभिनय करके :

  1. X{{a..c},{1..3}}
  2. X{a,{1..3}}Y X{b,{1..3}}Y X{c,{1..3}}Y

    (अर्थात A{a..c}Bकरने के लिए विस्तारित AaB AbB AcB, जहां Aहै X{और Bहै ,{1..3}Y)

  3. X{a,1}Y X{a,2}Y X{a,3}Y X{b,1}Y X{b,2}Y X{b,3}Y X{c,1}Y X{c,2}Y X{c,3}Y

  4. XaY X1Y XaY Xa2...

लेकिन मुझे ऐसा नहीं लगता है कि विशेष रूप से अधिक सहज और न ही उपयोगी (उदाहरण के लिए टिप्पणियों में केविन का उदाहरण देखें), अभी भी कुछ अस्पष्टता होगी जिस क्रम में विस्तार किया जाएगा, और यह कि कैसे csh(शेल जो ब्रेस पेश नहीं किया है) 70 के दशक के उत्तरार्ध में विस्तार, जबकि {1..3}फॉर्म बाद में (1995) से आया zshऔर {a..c}फिर बाद में (2004) से bash) ने किया।

ध्यान दें कि csh(शुरुआत से, 2BSD (1979) मैन पेज देखें ) ने इस तथ्य का दस्तावेजीकरण किया कि ब्रेस एक्सपेंशन को नेस्टेड किया जा सकता है, हालांकि स्पष्ट रूप से यह नहीं कहा गया है कि नेस्टेड ब्रेस एक्सपैंशन का विस्तार कैसे किया जाएगा। लेकिन आप कर सकते हैं पर देखने के csh1979 से कोड को देखने के लिए कैसे यह तो किया गया था। देखें कि यह वास्तव में घोंसले के शिकार से कैसे निपटता है, और यह बाहरी ब्रेसिज़ से शुरू होने का समाधान कैसे होता है।

किसी भी मामले में, मैं वास्तव में नहीं देखता कि कैसे विस्तार का {a..c},{1..3}कोई असर हो सकता है। वहाँ, ,एक ब्रेस विस्तार का एक ऑपरेटर नहीं है (जैसा कि यह ब्रेसिज़ के अंदर नहीं है), इसलिए किसी भी सामान्य चरित्र की तरह व्यवहार किया जाता है।


मेरे लिए अजीब लगता है कि बाहरी ब्रेसिज़ आंतरिक लोगों से पहले हल करने वाले हैं।
हॉक लागिंग

@ stéphane-chazelas इस अभिव्यक्ति को पार्स किया जा सकता है कि दो स्पष्ट तरीके हैं। इसे एक तरह से पार्स किया जाता है और दूसरे को क्यों नहीं? आपकी टिप्पणी स्पष्टीकरण नहीं देती है।
Igal

तो, यह स्पष्टीकरण समझ में आता है, लेकिन अगर यह "के रूप में विस्तारित किया जा रहा है ..." एक URL है?
xenoid

@xenoid मेरा अद्यतन समाधान देखें।
igal

1
@ (सभी): विस्तार पर विचार करें /dev/{h,s}d{a..d}{1..4,}। अब आप विस्तार करने के लिए यह भी शामिल करना चाहते हैं लगता है /dev/nullऔर /dev/zero। अगर ब्रेस विस्तार अंदर से बाहर काम करता है, तो यह विस्तार वास्तव में निर्माण के लिए कष्टप्रद होगा। लेकिन क्योंकि यह बाहर से काम करता है, यह काफी तुच्छ है:/dev/{null,zero,{h,s}d{a..d}{1..4,}}
केविन

7

यहाँ संक्षिप्त जवाब है। पहली अभिव्यक्ति में कॉमा को एक विभाजक के रूप में उपयोग किया जाता है, इसलिए ब्रेस का विस्तार केवल दो नेस्टेड सबएक्सप्रेस के संयोजन है। दूसरी अभिव्यक्ति में अल्पविराम ही है, एक एकल चरित्र उपसूचक रूप में व्यवहार किया तो उत्पाद भाव है कर रहे हैं का गठन किया।

आप जो याद कर रहे थे, वह परिभाषा थी कि कैसे ब्रेस-एक्सप्रेशन किए जाते हैं। यहाँ तीन संदर्भ दिए गए हैं:

एक अधिक विस्तृत विवरण इस प्रकार है।


आपने इस अभिव्यक्ति के परिणाम की तुलना की:

$ echo {{a..c},{1..3}}
a b c 1 2 3

इस अभिव्यक्ति के परिणाम:

$ echo {a..c},{1..3}
a,1 a,2 a,3 b,1 b,2 b,3 c,1 c,2 c,3

आप कहते हैं कि यह समझाना कठिन है, अर्थात यह प्रति-सहज है। क्या याद आ रही है कि कैसे ब्रेस-एक्सपेंशन संसाधित किया जाता है की एक औपचारिक परिभाषा है। आप ध्यान दें कि बैश मैनुअल पूर्ण परिभाषा नहीं देता है।

मैंने थोड़ी खोज की लेकिन मुझे लापता (पूर्ण, औपचारिक) परिभाषा नहीं मिली। इसलिए मैं स्रोत कोड गया:

स्रोत में उपयोगी टिप्पणियों की एक जोड़ी है। पहले ब्रेस विस्तार एल्गोरिथ्म का एक उच्च-स्तरीय अवलोकन है:

Basic idea:

Segregate the text into 3 sections: preamble (stuff before an open brace),
postamble (stuff after the matching close brace) and amble (stuff after
preamble, and before postamble).  Expand amble, and then tack on the
expansions to preamble.  Expand postamble, and tack on the expansions to
the result so far.

तो ब्रेस-एक्सपेंशन टोकन का प्रारूप निम्नलिखित है:

<PREAMBLE><AMBLE><POSTAMBLE>

विस्तार के लिए मुख्य प्रवेश-बिंदु एक फ़ंक्शन है जिसे brace_expandइस प्रकार वर्णित किया गया है:

Return an array of strings; the brace expansion of TEXT.

तो brace_expandफ़ंक्शन ब्रेस विस्तार अभिव्यक्ति का प्रतिनिधित्व करने वाला एक स्ट्रिंग लेता है और विस्तारित स्ट्रिंग्स की सरणी देता है।

इन दो अवलोकनों को मिलाकर हम देखते हैं कि एंबेल को स्ट्रिंग्स की एक सूची में विस्तारित किया गया है, जिनमें से प्रत्येक को प्रस्तावना पर संक्षिप्त किया गया है। इसके बाद पोस्टमैबल को स्ट्रिंग की एक सूची में विस्तारित किया जाता है, और पोस्टमैबल सूची में प्रत्येक स्ट्रिंग को प्रत्येक स्ट्रिंग पर प्रस्तावना / amble सूची (यानी दो सूचियों का उत्पाद बनता है) में समवर्ती किया जाता है। लेकिन यह वर्णित नहीं है कि कैसे एंबेल और पोस्टमबल को संसाधित किया जाता है। सौभाग्य से एक टिप्पणी है जो वर्णन करती है। एंबेल को एक फ़ंक्शन द्वारा संसाधित किया जाता है, expand_ambleजिसकी परिभाषा निम्नलिखित टिप्पणी से पहले होती है:

Expand the text found inside of braces.  We simply try to split the
text at BRACE_ARG_SEPARATORs into separate strings.  We then brace
expand each slot which needs it, until there are no more slots which
need it.

कोड में कहीं और हम देखते हैं कि BRACE_ARG_SEPARATOR को अल्पविराम के रूप में परिभाषित किया गया है। इससे यह स्पष्ट होता है कि एंबेल स्ट्रिंग्स की अल्पविराम से अलग की गई सूची है, जिनमें से कुछ ब्रेस-एक्सपेंशन एक्सप्रेशन भी हो सकते हैं। ये तार फिर एकल सरणी बनाते हैं। अंत में, हम यह भी देख सकते हैं कि बाद expand_ambleमें brace_expandफंक्शन को कहा जाता है और फिर पोस्टमैबल पर पुनरावर्ती कहा जाता है। यह हमें एल्गोरिथ्म का पूरा विवरण देता है।

कुछ अन्य (अनौपचारिक) संदर्भ हैं जो इस खोज को पुष्ट करते हैं।

एक संदर्भ के लिए, बैश हैकर्स विकी देखेंसंयोजन और नेस्टिंग पर अनुभाग आपके मुद्दे को काफी संबोधित नहीं करता है, लेकिन पृष्ठ ब्रेस विस्तार के वाक्यविन्यास / व्याकरण देता है, जो मुझे लगता है कि आपके प्रश्न का उत्तर देता है। सिंटैक्स निम्न पैटर्न द्वारा दिया गया है:

{string1,string2,...,stringN}

{<START>..<END>}

<PREAMBLE>{........}

{........}<POSTSCRIPT>

<PREAMBLE>{........}<POSTSCRIPT>

और पार्सिंग का वर्णन इस प्रकार है:

ब्रेस विस्तार का उपयोग मनमाने तार उत्पन्न करने के लिए किया जाता है। निर्दिष्ट स्ट्रिंग्स का उपयोग वैकल्पिक आसपास के प्रस्तावना और पोस्टस्क्रिप्ट के साथ सभी संभव संयोजनों को उत्पन्न करने के लिए किया जाता है ।

एक और संदर्भ के लिए, बैश बिगिनर्स गाइड पर एक नज़र डालें , जिसमें निम्नलिखित बातें हैं:

Brace expansion is a mechanism by which arbitrary strings may be generated. Patterns to be brace-expanded take the form of an optional PREAMBLE, followed by a series of comma-separated strings between a pair of braces, followed by an optional POSTSCRIPT. The preamble is prefixed to each string contained within the braces, and the postscript is then appended to each resulting string, expanding left to right.

तो ब्रेस-एक्सपोज़र एक्सप्रेशंस को पार्स करने के लिए हम बाएं-दाएं जाते हैं, प्रत्येक एक्सप्रेशन का विस्तार करते हैं और क्रमिक उत्पादों का निर्माण करते हैं (स्ट्रिंग-कंसेंट्रेशन के संचालन के संबंध में)।

अब अपनी पहली अभिव्यक्ति पर विचार करते हैं:

{{a..c},{1..3}}

बैश हैकर की विकी की भाषा में, यह पहले रूप से मेल खाता है:

{string1,string2,...,stringN}

जहां N=2, string1={a..c}और string2={1..3}- और अंदर ब्रेस विस्तार पहले प्रदर्शन किया जा रहा है और उनमें से प्रत्येक फॉर्म का है {<START>..<END>}। वैकल्पिक रूप से, हम कह सकते हैं कि यह एक ब्रेस-एक्सपेंशन एक्सप्रेशन है, जिसमें केवल एक एंबेल (कोई प्रस्तावना या पोस्टमैबल) नहीं है। एंबेल एक अल्पविराम से अलग की गई सूची है, इसलिए हम एक समय में सूची एक स्लॉट के माध्यम से जाते हैं, और जहां आवश्यक हो अतिरिक्त प्रदर्शन करते हैं। कोई भी उत्पाद नहीं बनता है क्योंकि आसन्न अभिव्यक्ति नहीं होती है (अल्पविराम का उपयोग विभाजक के रूप में किया जाता है)।

आगे आप अपनी दूसरी अभिव्यक्ति देखें:

{a..c},{1..3}

बैश हैकर विकी की भाषा में, यह अभिव्यक्ति फॉर्म से मेल खाती है:

{........}<POSTSCRIPT>

जहाँ पोस्टस्क्रिप्ट उप-अभिव्यक्ति है ,{1..3}। वैकल्पिक रूप से, हम यह कह सकते हैं कि इस अभिव्यक्ति में एक एंबेल ( {a..c}) और एक पोस्टएम्बल ( ,{1..3}) है। सूची में एंबेल का विस्तार किया जाता है a b cऔर फिर इनमें से प्रत्येक को पोस्टमैबल के विस्तार में प्रत्येक स्ट्रिंग्स के साथ समतल किया जाता है। पोस्टमबल को पुनरावर्ती रूप से संसाधित किया जाता है: इसमें एक प्रस्तावना ,और एक एमबल होता है {1..3}। यह सूची में विस्तारित है ,1 ,2 ,3। दो सूचियों a b cऔर ,1 ,2 ,3फिर उत्पाद सूची बनाने के लिए संयुक्त हैं a,1 a,2 a,3 b,1 b,2 b,3 c,1 c,2 c,3

यह इन अभिव्यक्तियों को कैसे पार्स किया जाता है, इसका एक प्यूसीडो-बीजीय विवरण देने में मदद मिल सकती है, जहां कोष्ठक "[]" एरे को निरूपित करते हैं, "+" सरणी समाकलन को दर्शाता है, और "*" कार्टेशियन उत्पाद को दर्शाता है (संघनन के संबंध में)।

यहां बताया गया है कि पहली अभिव्यक्ति का विस्तार कैसे किया जाता है (प्रति पंक्ति एक कदम):

{{a..c},{1..3}}
{a..c} + {1..3}
[a b c] + [1 2 3]
a b c 1 2 3

और यहां बताया गया है कि दूसरी अभिव्यक्ति का विस्तार कैसे किया जाता है:

{a..c},{1..3}
{a..c} * ,{1..3}
[a b c] * [,1 ,2 ,3]
a,1 a,2 a,3 b,1 b,2 b,3 c,1 c,2 c,3

2

मेरी समझ यह है:

आंतरिक ब्रेसिज़ को पहले (हमेशा की तरह) हल किया जाता है जो मुड़ता है

{{a..c},{1..3}}

में

{a,b,c,1,2,3}

क्योंकि ,ब्रेसिज़ के भीतर यह सिर्फ ब्रेस तत्वों को अलग करता है।

लेकिन के मामले में

{a..c},{1..3}

,ब्रेसिज़ यानी भीतर यह दोनों पक्षों पर ब्रेस क्रमपरिवर्तन के कारण एक साधारण चरित्र है नहीं है।


तो {a..c}या तो हल a,b,cया a b cनमी और डाओ जोन्स के आधार पर? साफ।
kubanczyk

यह थोड़ा भ्रमित करने वाला लगता है। यदि {{a..c},{1..3}}जैसा है {a,b,c,1,2,3}, तो {{a..c}.{1..3}}वैसा ही नहीं होना चाहिए {a,b,c.1,2,3}? बेशक यह मामला नहीं है।
इलकाचू

@ilkkachu क्यों वही होना चाहिए? ,ब्रेस विस्तार जुदाई चरित्र है, .नहीं है। एक साधारण चरित्र को विशेष के समान परिणाम क्यों देना चाहिए? c.1एक ब्रेस तत्व है। लेकिन में छोड़ दिया और सही पर ब्रेस विस्तार के लिए लंगर है। बाहरी ब्रेस के साथ ब्रेस विस्तार के लिए उपयोग किया जाता है क्योंकि उनकी सामग्री में ब्रेस विस्तार प्रारूप है, क्योंकि वे नहीं हैं क्योंकि उनकी सामग्री में वह प्रारूप नहीं है। {a..c}.{1..3}.,.
हॉउक लागिंग

@ हॉकिंग, ठीक है, अगर में {{a..c},{1..3}}बदल जाता है {a,b,c,1,2,3}तो कुछ अल्पविराम बस के बीच दिखाई दिया a, bऔर c। वे उसी तरह से क्यों दिखाई नहीं देंगे {a..c}.{1..3}? @Kubanczyk की टिप्पणी उसी चीज़ के बारे में है, अगर कॉमा वहाँ ऐसे ही दिखाई देते हैं, तो हमें कैसे पता चलेगा कि विस्तार कब कॉमा उत्पन्न करता है और कब नहीं? पाठ्यक्रम का उत्तर यह है, कि यह कभी भी अपने आप में कोई अल्पविराम उत्पन्न नहीं करता है, यह शब्दों की एक सूची बनाता है। तो कुछ भी नहीं है में बदल जाता है {a,b,c,1,2,3}या {a,b,c.1,2,3}
ilkachachu

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