कोई अच्छा कारण नहीं है
[[ $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लगाया जाता है b। WORDa|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 ]]
अन्य गोले के लिए पोर्टेबिलिटी के साथ मदद करता है।
|विशेष है) चालू है[[ $var = $pattern ]]। संस्करणों औरshoptविकल्प कॉन्फ़िगरेशन को अलग करना दिलचस्प होगा जहां यह व्यवहार देखा जाता है - यदि यह केवल उन पर है जहांextglobया तो डिफ़ॉल्ट या स्पष्ट कॉन्फ़िगरेशन से है, ठीक है, वहां हम हैं।