ब्रैकेट में अभिव्यक्ति (श्रेणियों के बिना) अप्रत्याशित चरित्र से मेल खाती है


20

मैं लिनक्स पर बैश का उपयोग कर रहा हूं। मुझे कथन के अनुसार निम्नलिखित में से एक सफलता मिल रही है, लेकिन क्या यह एक असफल कोड नहीं होना चाहिए?

if [[  = [⅕⅖⅗] ]] ; then echo yes ; fi

वर्ग किसी भी वर्ण के बराबर नहीं है, इसलिए मैं यह नहीं देखता कि मुझे सफलता कोड क्यों मिले।

मेरे लिए अपने मामले में डबल कोष्ठक रखना महत्वपूर्ण है।

क्या इस परिदृश्य में कोई अन्य तरीका है, या कोई अन्य सुझाव है?


2
संभवतः उन सभी पात्रों का एक परिणाम आपके लोकेल में अपरिभाषित सॉर्टिंग क्रम है (और इस प्रकार समान है)। ऑस्टिन समूह में चल रही, संबंधित चर्चा देखें । इसे ठीक करने के लिए लोकेल को C में बदलें
स्टीफन चेजलस

1
क्षमा करें, Cयहाँ ऐसा नहीं होगा क्योंकि यह एकल-बाइट वर्ण नहीं है। C.UTF-8जहां उपलब्ध होगा वहीं करेंगे।
स्टीफन चेज़लस

11
बधाई हो, आप स्टीफन को अपने पहले प्रश्न पर एक ऑस्टिन ग्रुप थ्रेड को जोड़ने के लिए बुलाने में कामयाब रहे। यह कम से कम ⅗ के बराबर होना चाहिए। या Or या यहां तक ​​कि ■ आंतरिक, जैसा कि स्पष्ट रूप से वही हैं। यूनिक्स और लिनक्स में आपका स्वागत है , और कृपया दिलचस्प सवाल लाते रहें।
अपमानजनक

जवाबों:


29

यह उन वर्णों का एक ही क्रमबद्ध क्रम है।

आप यह भी देखेंगे कि

sort -u << EOF




EOF

केवल एक लाइन देता है।

या वो:

expr  = 

सच लौटाता है (POSIX द्वारा आवश्यक)।

जीएनयू सिस्टम के साथ भेजे जाने वाले अधिकांश स्थानों में वर्णों की एक संख्या होती है (और वर्णों के अनुक्रम भी (क्रमबद्ध करने वाले अनुक्रम)) जिनमें क्रमबद्ध क्रम होता है। उन the लोगों के मामले में, यह इसलिए है क्योंकि यह आदेश परिभाषित नहीं है, और जिन वर्णों के क्रम को परिभाषित नहीं किया गया है, वे GNU सिस्टम में समान क्रमबद्ध क्रम रखते हैं। ऐसे वर्ण हैं जिन्हें स्पष्ट रूप से Ş और Ș जैसे समान क्रम वाले आदेश के रूप में परिभाषित किया गया है (हालांकि यह स्पष्ट रूप से मेरे लिए कोई तर्क नहीं है) कि यह कैसे किया जाता है।

यह काफी आश्चर्यजनक और संगीन व्यवहार का स्रोत है। मैंने हाल ही में ऑस्टिन समूह (POSIX और एकल UNIX विनिर्देशन के पीछे निकाय) की मेलिंग सूची पर मुद्दा उठाया है और चर्चा अभी भी 2015-04-03 तक जारी है।

इस मामले में, चाहे वह कहां से [y]मेल खाना चाहिए और उसी के अनुसार यह मेरे लिए अस्पष्ट है, लेकिन चूंकि एक ब्रैकेट अभिव्यक्ति का मतलब एक कोलाजिंग तत्व से मेल खाता है, जो यह बताता है कि व्यवहार अपेक्षित है।xxybash

किसी भी मामले में, मुझे लगता है [⅕-⅕]या कम से कम [⅕-⅖]मेल खाना चाहिए

आप देखेंगे कि विभिन्न उपकरण अलग तरह से व्यवहार करते हैं। ksh93 की तरह व्यवहार करता है bash, GNU grepया sedनहीं। कुछ अन्य गोले अलग व्यवहार करते हैं जैसे yashकुछ और भी छोटी गाड़ी।

एक सुसंगत व्यवहार करने के लिए, आपको एक स्थान की आवश्यकता होती है जहाँ सभी वर्ण अलग-अलग प्रकार के होते हैं। सी लोकेल एक विशिष्ट है। हालाँकि अधिकांश सिस्टम पर C लोकेल में सेट किया गया वर्ण ASCII है। जीएनयू सिस्टम पर, आपके पास आमतौर पर एक C.UTF-8लोकेल तक पहुंच होती है, जिसे यूटीएफ -8 चरित्र पर काम करने के बजाय उपयोग किया जा सकता है।

इसलिए:

(export LC_ALL=C.UTF-8; [[  = [⅕⅖⅗] ]])

या मानक समकक्ष:

(export LC_ALL=C.UTF-8
 case  in ([⅕⅖⅗]) true;; (*) false; esac)

झूठे लौटना चाहिए।

एक अन्य विकल्प केवल LC_COLLATEC पर सेट किया जाएगा जो GNU सिस्टम पर काम करेगा, लेकिन दूसरों पर जरूरी नहीं कि यह मल्टी-बाइट कैरेक्टर के क्रम को निर्दिष्ट करने में विफल हो सकता है।


इसका एक सबक यह है कि समानता एक धारणा के रूप में स्पष्ट नहीं है क्योंकि जब यह तार की तुलना करने की बात आती है तो कोई उम्मीद नहीं करेगा। समानता का मतलब हो सकता है, सबसे कम से कम सख्त से।

  1. बाइट्स और सभी बाइट घटकों की समान संख्या का समान मूल्य है।
  2. समान वर्ण और सभी वर्ण समान हैं (उदाहरण के लिए, वर्तमान वर्णमाला में समान कोडपाइंट को देखें)।
  3. दो तार में लोकेल के कॉलेशन एल्गोरिथ्म के अनुसार एक ही क्रमबद्ध क्रम होता है (अर्थात, न तो <b और न ही b> a सत्य है)।

अब, 2 या 3 के लिए, मान लें कि दोनों तारों में वैध वर्ण हैं। UTF-8 और कुछ अन्य एन्कोडिंग में, बाइट्स के कुछ अनुक्रम वैध वर्ण नहीं बनाते हैं।

1 और 2 जरूरी नहीं है कि इसकी वजह से समतुल्य हो, या क्योंकि कुछ पात्रों में एक से अधिक संभव एन्कोडिंग हो सकते हैं। यही कारण है कि आम तौर पर आईएसओ-2022-जेपी की तरह स्टेटफुल एनकोडिंग जहां का मामला है Aके रूप में व्यक्त किया जा सकता है 41या 1b 28 42 41( 1b 28 42, मैं हालांकि जा रहा है ASCII करने के लिए स्विच करने के लिए अनुक्रम और आप के रूप में आप चाहते हैं उन में से कई, कि एक फर्क नहीं होगा के रूप में सम्मिलित कर सकते हैं) उन प्रकार के एन्कोडिंग का अभी भी उपयोग होने की उम्मीद नहीं है, और जीएनयू उपकरण कम से कम आमतौर पर उनके साथ ठीक से काम नहीं करते हैं।

यह भी सावधान रहें कि अधिकांश गैर-जीएनयू उपयोगिताओं 0 बाइट मान (एएससीआईआई में एनयूएल चरित्र) के साथ सौदा नहीं कर सकती हैं।

उन परिभाषाओं में से किसका उपयोग किया जाता है यह उपयोगिता और उपयोगिता कार्यान्वयन या संस्करण पर निर्भर करता है। उस पर POSIX 100% स्पष्ट नहीं है। C लोकेल में, सभी 3 बराबर हैं। उस YMMV के बाहर।


एक और आम मामला जहां 1 और 2 अलग-अलग हैं, वे यूनिकोड में पात्रों के संयोजन जैसी चीजों के साथ हैं।
गिलेस एसओ- बुराई को रोकना '

@ गिल्स, कॉम्बिनेशन कैरेक्टर अपने खुद के कैरेक्टर होते हैं। संयोजन एक अंगूर / कोशिका बनाता है, लेकिन फिर भी कई वर्णों से बनता है। é (U + 00E9) और é (e द्वारा पीछा किया गया U + 0301) एक ही अंगूर हैं, लेकिन चरित्र के दो अलग-अलग क्रम (कम से कम POSIX एपीआई बिंदु से)। 1 और 2 तक, वे अलग होंगे। 3 से, वे उसी पर विचार कर सकते थे यदि U + 0301 में इसके सभी कोलाज वेट "IGNORE" पर सेट होते, लेकिन यह आमतौर पर वैसा नहीं होता जैसा कि आम तौर पर डायक्ट्रीक्स के आदेश पर तय करना चाहते हैं।
स्टीफन चेजेलस 13

यह आमतौर पर विचार करने éऔर एक ही स्ट्रिंग होने के लिए वांछनीय है , लेकिन नहीं e। POSIX की टक्कर आदेश की धारणा शायद ही कभी सही होती है, यह बहुत अधिक वर्णों पर आधारित होती है और इसमें छंटनी के अधिकांश सामान्य तरीकों का हिसाब नहीं होता है (उदाहरण के लिए फ्रांसीसी शब्दकोश शब्दों को क्रमबद्ध करने के लिए एक शाब्दिक आदेश का उपयोग नहीं करते हैं: वे उच्चारणों को नजरअंदाज करने के साथ पहले लेक्सोग्राफिक पास करते हैं और तब संबंधों को तय करने के लिए लहजे का उपयोग करें)।
गिल्स एसओ- बुराई को रोकना '

@ गिल्स, हां। इसीलिए मैं कहता हूँ कि glibc लोकेशन्स में एक ही तरह के क्रम (जानबूझकर) रखने वाले अक्षर कम मायने रखते हैं। É बनाम é आमतौर पर स्ट्रिंग्स पर कुछ परिवर्तन करके पता किया जाता है जैसे कि विहित विघटन (जब आप केस-असंवेदनशील छँटाई / मिलान करना चाहते हैं तो पहले लोअर केस में कन्वर्ट करना चाहते हैं)। इस विषय पर कुछ अच्छे संदर्भ के लिए ICU गाइड भी देखें ।
स्टीफन चेजलस

@ गिल्स, पोसिक्स लोकेल कोलॉज एल्गोरिथ्म में वेट उस फ्रेंच डिक्शनरी को छांट सकते हैं। इस तरह वजन काम होता है। एक प्रथम पास प्राथमिक वज़न का उपयोग करता है (जहाँ e और é (और E और primary) का समान है और तीव्र उच्चारण के संयोजन को अनदेखा किया जाता है) एक दूसरा पास (यदि बराबर है) उच्चारणों की जाँच करता है, तो एक 3-पास कैपिटलाइज़ेशन ...
स्टेपल चेज़लस

-3

आप इसे गलत कर रहे हैं, =और ऐसा ==नहीं है।

इन उदाहरणों की कोशिश करें:

if [[ "■" == "[⅕⅖⅗]" ]] ; then echo yes ; else echo no ; fi

if [[ "1" == "1" ]] ; then echo yes ; else echo no ; fi

if [[ "■" == "■" ]] ; then echo yes ; else echo no ; fi

1
यह सच नहीं है। POSIX निर्दिष्ट करता है कि ऑपरेटर =का उपयोग समानता की जांच के लिए किया जाना चाहिए। समस्या अनुपलब्ध उद्धरण हैं, ऑपरेटर नहीं।
scai

1
अनुभाग man bashमें भी कहा गया है [[: "= ऑपरेटर == के बराबर है।"
माइक्स 3'15

1
@ सीसाई, पोसिक्स [[...]]ऑपरेटर को निर्दिष्ट नहीं करता है । और = और == गोले में समान हैं जो इसे लागू किया गया था (ksh / bash / zsh) और पैटर्न मिलान के लिए, समानता नहीं।
स्टीफन चेज़लस

एक पैटर्न की तुलना करते समय, पैटर्न को उद्धृत नहीं किया जाना चाहिए, अन्यथा इसे शाब्दिक स्ट्रिंग के रूप में लिया जाता है, इसलिए पहले परीक्षण में "नहीं"।
xhienne
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.