एक ग्लोब पैटर्न में `` का इलाज क्यों नहीं किया जाता है?


13

मेरा सवाल यह है कि शेल चर में नियमित अभिव्यक्ति को कैसे संग्रहीत किया जाता है जो शेल के लिए विशेष वर्णों के उद्धरण के साथ समस्याओं से बचता है?

  1. कोई त्रुटि क्यों है:

    $ [[ $a = a|b ]]  
    bash: syntax error in conditional expression: unexpected token `|'
    bash: syntax error near `|b'

    [[ ... ]]के दूसरे ऑपरेंड के अंदर =एक ग्लोबिंग पैटर्न होने की उम्मीद है।

    क्या a|bएक वैध ग्लोबिंग पैटर्न नहीं है? क्या आप बता सकते हैं कि यह किस सिंटैक्स नियम का उल्लंघन करता है?

  2. नीचे कुछ टिप्पणी ऐसे बिंदुओं के बारे में बताती है, जिन्हें |पाइप के रूप में समझा जाता है।

    फिर regex पैटर्न बनाने के =लिए ग्लोब पैटर्न के =~लिए |काम करना

    $ [[ $a =~ a|b ]]

    मैंने अपनी पिछली पोस्ट में लर्निंग बैश p180 से सीखा जो कि व्याख्या की शुरुआत में पाइप के रूप में पहचाना जाता है, यहां तक ​​कि व्याख्या के किसी भी अन्य चरण से पहले (उदाहरणों में सशर्त अभिव्यक्तियों को पार्स सहित)। तो कैसे उपयोग करते समय regex ऑपरेटर के रूप में पहचाना जा सकता है , अवैध उपयोग में पाइप के रूप में पहचाने बिना, उपयोग करते समय ? इससे मुझे लगता है कि भाग 1 में वाक्य रचना त्रुटि का मतलब यह नहीं है कि इसे पाइप के रूप में व्याख्या किया गया है।||=~=|

    प्रत्येक पंक्ति जिसे शेल मानक इनपुट या स्क्रिप्ट से पढ़ता है उसे पाइपलाइन कहा जाता है; इसमें एक या अधिक कमांड शून्य या अधिक पाइप वर्णों (!) द्वारा अलग किए गए हैं। प्रत्येक पाइपलाइन के लिए यह पढ़ता है, शेल इसे कमांड में तोड़ता है, पाइप लाइन के लिए I / O सेट करता है, फिर प्रत्येक कमांड के लिए निम्न करता है (चित्र 7-1):

धन्यवाद।


1
ध्यान दें कि बैश के कुछ संस्करणों में, राइट-साइड की ओर डिफ़ॉल्ट रूप से एक्सग्लोब पार्सिंग (जहां |विशेष है) चालू है [[ $var = $pattern ]]। संस्करणों और shoptविकल्प कॉन्फ़िगरेशन को अलग करना दिलचस्प होगा जहां यह व्यवहार देखा जाता है - यदि यह केवल उन पर है जहां extglobया तो डिफ़ॉल्ट या स्पष्ट कॉन्फ़िगरेशन से है, ठीक है, वहां हम हैं।
चार्ल्स डफी

2
BTW, अगर आप पाइप के चरित्र के मामले को पार्सिंग के एक पूर्व चरण के साथ हस्तक्षेप करने के लिए कुछ अधिक व्यापक रूप से शासन करना चाहते थे (जो मैं सहमत हूं ऐसा नहीं हो रहा है, लेकिन यह पाठक के लिए उतना स्पष्ट नहीं है जितना कि यह हो सकता है), आप! उपयोग करें pattern='a|b'और फिर $patternRHS पर अयोग्य का विस्तार करें ।
चार्ल्स डफी

@CharlesDuffy, वह बिंदु था जो प्रश्नोत्तर में बनाया जा रहा था, जो कि यह प्रश्न अनुवर्ती है।
स्टीफन चेजलस

आह - संदर्भ समझ में आता है; और यहां आपका जवाब बकाया है। दोनों ही मायने में धन्यवाद।
चार्ल्स डफी

टिम, नीचे दिए गए किसी भी उत्तर को अपने प्रश्न का उत्तर दें? कृपया एक को स्वीकार करने पर विचार करें। धन्यवाद!
जेफ स्कालर

जवाबों:


13

कोई अच्छा कारण नहीं है

[[ $a = a|b ]]

परीक्षण के बजाय एक त्रुटि की रिपोर्ट करनी चाहिए कि क्या $ a a|bस्ट्रिंग है, जबकि [[ $a =~ a|b ]]कोई त्रुटि वापस नहीं होती है।

एकमात्र कारण यह है कि |आम तौर पर (बाहर और अंदर [[ ... ]]) एक विशेष चरित्र होता है। उस [[ $a =स्थिति में, bashएक प्रकार के टोकन की अपेक्षा करता है जो एक सामान्य WORD होता है जैसे तर्क या एक सामान्य शेल कमांड लाइन में पुनर्निर्देशन के लक्ष्य (लेकिन यदि extglobविकल्प 4.1 के बाद से सक्षम किया गया था)।

( यहाँ WORD के द्वारा , मैं एक शब्द का उल्लेख एक काल्पनिक खोल व्याकरण में करता हूं, जैसे कि POSIX विनिर्देश द्वारा वर्णित है , यह कुछ ऐसा है कि शेल एक साधारण शेल कमांड लाइन में टोकन के रूप में पार्स करेगा, अंग्रेजी जैसे शब्दों की अन्य परिभाषा नहीं। अक्षरों के अनुक्रम या गैर-रिक्ति वर्णों के अनुक्रम में से एक। foo"bar baz", $(echo x y)दो ऐसे शब्द हैं जो WORD s) हैं।

एक सामान्य शेल कमांड लाइन में:

echo a|b

को echo aलगाया जाता है bWORDa|b नहीं है , यह तीन टोकन हैं: एक WORD , एक टोकन और एक WORD टोकन।a |b

जब उपयोग किया जाता है [[ $a = a|b ]], तो bashएक WORD की अपेक्षा करता है जो इसे मिलता है ( a), लेकिन फिर एक अप्रत्याशित |टोकन पाता है जो त्रुटि का कारण बनता है।

दिलचस्प bashबात यह है कि इसमें कोई शिकायत नहीं है:

[[ $a = a||b ]]

क्योंकि यह अब एक aटोकन है जिसके बाद एक ||टोकन आता है b, इसलिए इसे उसी तरह से पार्स किया जाता है:

[[ $a = a || b ]]

जो परीक्षण कर रहा $aहै aकि bस्ट्रिंग गैर-रिक्त है।

में अब:

[[ $a =~ a|b ]]

bashएक ही पार्सिंग नियम नहीं हो सकता। एक ही पार्सिंग नियम होने का मतलब यह होगा कि ऊपर एक त्रुटि देगा और यह |सुनिश्चित करने के लिए a|bकि किसी एक शब्द को उद्धृत करने की आवश्यकता होगी । लेकिन, यदि आप करते हैं, तो 3.2 बैश करें:

[[ $a =~ 'a|b' ]]

यह अब a|bregexp के खिलाफ नहीं, बल्कि regexp के खिलाफ मेल a\|bखा रहा है। यही है, शेल उद्धरण के रीजैक्स ऑपरेटर के विशेष अर्थ को हटाने का दुष्प्रभाव है। यह एक विशेषता है, इसलिए व्यवहार एक के समान है [[ $a = "?" ]], लेकिन वाइल्डकार्ड पैटर्न (उपयोग में [[ $a = pattern ]]) शेल वर्क्स हैं (उदाहरण के लिए ग्लब्स में उपयोग किया जाता है), जबकि रीजैक्स नहीं हैं।

तो bashसब विस्तारित regexp ऑपरेटरों कि अन्यथा साधारण तरीके से की तरह विशेष खोल चरित्र के इलाज के लिए है |, (, )वह भिन्न की एक बहस को पार्स =~ऑपरेटर।

फिर भी, उस पर ध्यान दें

 [[ $a =~ (ab)*c ]]

अब काम करता है,

 [[ $a =~ [)}] ]]

ऐसा नहीं करता। आप की जरूरत है:

 [[ $a =~ [\)}] ]]
 [[ $a =~ [')'}] ]]

जो पिछले संस्करणों में bashगलत तरीके से बैकस्लैश पर मेल करेगा। वह एक तय था, लेकिन

 [[ $a =~ [^]')'] ]]

करता नहीं है जैसे कि यह उदाहरण के लिए चाहिए बैकस्लैश पर मेल खाते हैं। क्योंकि bashयह महसूस करने में विफल रहता है कि )कोष्ठक के भीतर है, इसलिए )परिणाम के परिणामस्वरूप बच जाता है जो [^]\)]किसी भी वर्ण पर मेल खाता है ], लेकिन , \और )

ksh93 उस मोर्चे पर बहुत बदतर कीड़े हैं।

इसमें zsh, यह एक सामान्य शेल शब्द है जो अपेक्षित है और regexp ऑपरेटरों को उद्धृत करना regexp ऑपरेटरों के अर्थ को प्रभावित नहीं करता है।

[[ $a =~ 'a|b' ]]

a|bRegexp के खिलाफ मिलान कर रहा है ।

इसका मतलब =~है कि [/ testकमांड में भी जोड़ा जा सकता है :

[ "$a" '=~' 'a|b' ]
test "$a" '=~' 'a|b'

(में भी काम करते हैं yash। के रूप =~में उद्धृत करने की जरूरत है एक विशेष शेल ऑपरेटर है)।zsh=something

बैश 3.1 जैसा व्यवहार करते थे zsh। यह 3.2 में बदल गया, संभवतः इसके साथ संरेखित करने के लिए ksh93(भले ही bashवह शेल था जो पहली बार आया था [[ =~ ]]), लेकिन आप अभी भी कर सकते हैं BASH_COMPAT=31या shopt -s compat31पिछले व्यवहार को वापस कर सकते हैं (सिवाय इसके कि 3.1 [[ $a =~ a|b ]]में एक त्रुटि लौटाएंगे bash, यह अब और नहीं करता है) में bash -O compat31के नए संस्करणों के साथ bash)।

आशा है कि यह स्पष्ट करता है कि मैंने क्यों कहा कि नियम भ्रामक थे और इसका उपयोग क्यों कर रहे थे:

[[ $a =~ $var ]]

अन्य गोले के लिए पोर्टेबिलिटी के साथ मदद करता है।


zsh भी किसी त्रुटि की रिपोर्ट कर रहा है [[ $a = a|b ]]
NotAnUnixNazi

@ आइसाक, हां, यह बात मैं यहां बता रहा हूं। a|bएक खोल नहीं है शब्द यहाँ, यह a, |और bटोकन। जैसे echo a|bकि ग्लोब a|bका उत्पादन या विस्तार नहीं करता है a|b, आपको |यह उद्धृत करने की आवश्यकता है क्योंकि यह एक विशेष शेल वर्ण है जो उस संदर्भ में अमान्य है। एक zsh वाइल्डकार्ड ऑपरेटर के रूप में काम करेगा [[ $a = (a|b) ]]जैसे काम echo (a|b)करेगा (a|b)
स्टीफन चेज़लस

आपके उत्तर पर शब्द और व्याख्या केवल नाम बैश है। वह संपूर्ण सत्य नहीं है।
NotAnUnixNazi

11

स्टैंडर्ड globs ( "फ़ाइल नाम विस्तार") कर रहे हैं: *, ?, और [ ... ]|मानक (गैर-अतिरिक्त) सेटिंग्स में एक मान्य ग्लोब ऑपरेटर नहीं है।

प्रयत्न:

shopt -s extglob
[[ a = @(a|b) ]] && echo matched

1
धन्यवाद। लेकिन |शाब्दिक रूप से अलग क्यों नहीं किया गया है? वाक्य रचना त्रुटि क्यों है?
टिम

1
यह उद्धृत नहीं किया गया था।
जेफ स्कालर

3
मानक सेटिंग्स में, |एक ग्लोब ऑपरेटर नहीं है, इसलिए |उद्धृत किए बिना शाब्दिक रूप से व्याख्या नहीं की जाती है? तो क्यों एक वाक्यविन्यास त्रुटि है?
टिम

1
|एक नियंत्रण चरित्र है; यह कभी भी एक शाब्दिक चरित्र के रूप में नहीं माना जाता है कि एक पत्र या संख्या है।
Chepner

3
क्योंकि उस मोड में शेल को पाइप के पुनर्निर्देशन वाले पात्र की उम्मीद नहीं थी कि वह अभी तक बंद नहीं हुआ है [[]]। [[ $a = aएक मान्य कमांड नहीं है जिसका आउटपुट किसी अन्य प्रक्रिया में डाला जा सकता है (कम से कम शेल ने सोचा कि आप क्या करने की कोशिश कर रहे थे)।
जेसन सी

5

यदि आप एक रेगेक्स मैच चाहते हैं तो परीक्षण होगा:

[[ "$a" =~ a|b ]]

@ समय आप अपने वर्तमान प्रश्न का लगातार संपादन न करते हुए नए प्रश्न खोल रहे होंगे।
बागीचा जूल

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