दिलचस्प पोस्ट
जावास्क्रिप्ट में स्ट्रिंग में स्ट्रिंग को कैसे परिवर्तित करें? गतिशील रूप से three.js के साथ एक रेखा खींचना जीआईटी रीसेट के बाद अस्थिर परिवर्तन छोड़े गए क्या सबसे अच्छा / सामान्य शांत यूआरएल क्रिया और क्रियाएं हैं? std :: endl अज्ञात प्रकार का है जब ओवरलोडिंग ऑपरेटर << इंटरफ़ेस या अमूर्त वर्ग? Perceptron सीखना एल्गोरिथ्म 0 करने के लिए नहीं converging फ़ाइलों को संसाधित करने के बाद मैं फ़ाइलों को एक संग्रह फ़ोल्डर में कैसे स्थानांतरित कर सकता हूं? Jquery मोबाइल के लिए गतिशील रूप से एचटीएमएल जोड़ने के बाद एक अनुभाग को रीफ्रेश करें विजुअल स्टूडियो में जीसीसी स्टाइल कमजोर है? आर में मिश्रित संख्याओं और अक्षरों के तारों का संख्यात्मक हिस्सा निकालें पायथन के किसी भी और सभी फ़ंक्शन कैसे काम करते हैं? बूस्ट :: एएसआईओ: io_service.run () बनाम पोल () या मैं कैसे बढ़ा सकते हैं :: मुख्य लूप में एएसआईओ एंड्रॉइड में अरायसूची सूचकांकऑटोऑफ़बाउंड अपवाद को समझें फ़्लोटिंग पॉइंट संख्या गलत क्यों हैं?

जावा रेगुलर एक्सप्रेशंस में \ w और \ b के लिए यूनिकोड समकक्ष?

कई आधुनिक रेगेक्स क्रियान्वयन \w अक्षर वर्ग आशुलिपि की व्याख्या "किसी भी पत्र, अंक या विराम चिह्न को जोड़ने" (आमतौर पर: अंडरस्कोर) करते हैं। इस तरह, एक regex जैसे \w+ जैसे élève , GOÄ_432 , GOÄ_432 या gefräßig शब्दों से मेल खाता है

दुर्भाग्य से, जावा नहीं है जावा में, \w [A-Za-z0-9_] तक सीमित है यह मुश्किल से ऊपर उल्लिखित जैसे अन्य समस्याओं के बीच मिलान करने वाले शब्द बनाता है।

यह भी ऐसा प्रतीत होता है कि \b शब्द विभाजक उन स्थानों में मेल खाता है जहां इसे नहीं होना चाहिए।

एनएटी जैसे, यूनिकोड-जागरूक \w या \b जावा के सही समीकरण क्या होगा? यूनिकोड-जागरूकता बनाने के लिए कौन-से अन्य शॉर्टकट्स "पुनः लिखने" की आवश्यकता है?

वेब के समाधान से एकत्रित समाधान "जावा रेगुलर एक्सप्रेशंस में \ w और \ b के लिए यूनिकोड समकक्ष?"

सोर्स कोड

पुनर्लेखन कार्यों के लिए स्रोत कोड जो मैं नीचे चर्चा करता हूं यहां उपलब्ध है ।

जावा 7 में अपडेट करें

जेडीके 7 के लिए सूर्य के अद्यतित Pattern वर्ग में एक अद्भुत नया झंडा है, UNICODE_CHARACTER_CLASS , जो सब कुछ ठीक से काम करता है। यह पैटर्न के अंदर के लिए एक एम्बेडेबल (?U) रूप में उपलब्ध है, ताकि आप इसे String क्लास के आवरण के साथ भी इसका उपयोग कर सकें। यह भी कई अन्य गुणों के लिए परिभाषाओं को सुधारने के लिए खेलें भी हैं यह अब यूनिकोड स्टैंडर्ड को ट्रैक करता है, यूटीएस # 18 से दोनों RL1.2 और RL1.2a में : यूनिकोड रेगुलर एक्सप्रेशंस यह एक रोमांचक और नाटकीय सुधार है, और इस महत्वपूर्ण प्रयास के लिए विकास टीम की सराहना की जानी है।


जावा के रेगेक्स यूनिकोड समस्याएं

जावा रेगेक्सस के साथ समस्या यह है कि पर्ल 1.0 चार्क्लास बच निकला – अर्थ \w , \b , \s , \d और उनकी पूरक – जावा में युनिकोड के साथ काम करने के लिए विस्तारित नहीं हैं इनमें से एक अकेले, \b कुछ विस्तारित शब्दों का आनंद उठाता है, लेकिन ये नक्शा न तो \w , न ही यूनिकोड पहचानकर्ताओं के साथ , और न ही यूनिकोड लाइन-ब्रेक गुणों के लिए ।

इसके अतिरिक्त, जावा में POSIX गुण इस प्रकार पहुंचाए जाते हैं:

 POSIX syntax Java syntax [[:Lower:]] \p{Lower} [[:Upper:]] \p{Upper} [[:ASCII:]] \p{ASCII} [[:Alpha:]] \p{Alpha} [[:Digit:]] \p{Digit} [[:Alnum:]] \p{Alnum} [[:Punct:]] \p{Punct} [[:Graph:]] \p{Graph} [[:Print:]] \p{Print} [[:Blank:]] \p{Blank} [[:Cntrl:]] \p{Cntrl} [[:XDigit:]] \p{XDigit} [[:Space:]] \p{Space} 

यह एक वास्तविक गड़बड़ है, क्योंकि इसका अर्थ है कि Alpha , Lower और Space जैसी चीजें जावा मैप में यूनिकोड Alphabetic , Lowercase , या Whitespace गुणों के लिए नहीं होती हैं। यह बेहद परेशान है जावा के यूनिकोड संपत्ति का समर्थन कड़ाई से एंटिमिल्लियल है , जिसके द्वारा मेरा मतलब है कि यह पिछले दशक में किसी यूनिकोड संपत्ति का समर्थन नहीं करता है।

सफेद स्थान के बारे में अच्छी तरह से बात करने में सक्षम नहीं है सुपर-कष्टप्रद निम्न तालिका पर विचार करें उन प्रत्येक कोड बिंदुओं के लिए, जावा के लिए जे-परिणाम कॉलम और पर्ल या किसी अन्य पीसीईआर-आधारित रेगेक्स इंजन के लिए पी-परिणाम कॉलम दोनों ही हैं:

  Regex 001A 0085 00A0 2029 JPJPJPJP \s 1 1 0 1 0 1 0 1 \pZ 0 0 0 0 1 1 1 1 \p{Zs} 0 0 0 0 1 1 0 0 \p{Space} 1 1 0 1 0 1 0 1 \p{Blank} 0 0 0 0 0 1 0 0 \p{Whitespace} - 1 - 1 - 1 - 1 \p{javaWhitespace} 1 - 0 - 0 - 1 - \p{javaSpaceChar} 0 - 0 - 1 - 1 - 

देखना है कि?

वास्तव में उन सभी जावा सफेद स्थान परिणामों में से हर एक यूनिकोड के अनुसार गलत है। यह एक बहुत बड़ी समस्या है जावा को सिर्फ गड़बड़ कर दिया गया है, जो वर्तमान अभ्यास के अनुसार "गलत" और यूनिकोड के अनुसार उत्तर देते हैं। इसके अलावा जावा आपको वास्तविक यूनिकोड गुणों तक पहुंच भी नहीं देता है! वास्तव में, जावा किसी भी प्रॉपर्टी का समर्थन नहीं करता जो कि यूनिकोड व्हाइटस्पेस से मेल खाती है।


उन सभी समस्याओं का हल, और अधिक

इस और कई अन्य संबंधित समस्याओं से निपटने के लिए, कल मैंने एक 14 वीं वर्गरेखा को पुनः लिखने वाले पैटर्न स्ट्रिंग को फिर से लिखने के लिए एक जावा फ़ंक्शन लिखा था:

 \w \W \s \S \v \V \h \H \d \D \b \B \X \R 

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

छोटी कहानी यह है कि मेरा कोड उन 14 लोगों को पुनः लिखता है:

 \s => [\u0009-\u000D\u0020\u0085\u00A0\u1680\u180E\u2000-\u200A\u2028\u2029\u202F\u205F\u3000] \S => [^\u0009-\u000D\u0020\u0085\u00A0\u1680\u180E\u2000-\u200A\u2028\u2029\u202F\u205F\u3000] \v => [\u000A-\u000D\u0085\u2028\u2029] \V => [^\u000A-\u000D\u0085\u2028\u2029] \h => [\u0009\u0020\u00A0\u1680\u180E\u2000-\u200A\u202F\u205F\u3000] \H => [^\u0009\u0020\u00A0\u1680\u180E\u2000\u2001-\u200A\u202F\u205F\u3000] \w => [\pL\pM\p{Nd}\p{Nl}\p{Pc}[\p{InEnclosedAlphanumerics}&&\p{So}]] \W => [^\pL\pM\p{Nd}\p{Nl}\p{Pc}[\p{InEnclosedAlphanumerics}&&\p{So}]] \b => (?:(?<=[\pL\pM\p{Nd}\p{Nl}\p{Pc}[\p{InEnclosedAlphanumerics}&&\p{So}]])(?![\pL\pM\p{Nd}\p{Nl}\p{Pc}[\p{InEnclosedAlphanumerics}&&\p{So}]])|(?<![\pL\pM\p{Nd}\p{Nl}\p{Pc}[\p{InEnclosedAlphanumerics}&&\p{So}]])(?=[\pL\pM\p{Nd}\p{Nl}\p{Pc}[\p{InEnclosedAlphanumerics}&&\p{So}]])) \B => (?:(?<=[\pL\pM\p{Nd}\p{Nl}\p{Pc}[\p{InEnclosedAlphanumerics}&&\p{So}]])(?=[\pL\pM\p{Nd}\p{Nl}\p{Pc}[\p{InEnclosedAlphanumerics}&&\p{So}]])|(?<![\pL\pM\p{Nd}\p{Nl}\p{Pc}[\p{InEnclosedAlphanumerics}&&\p{So}]])(?![\pL\pM\p{Nd}\p{Nl}\p{Pc}[\p{InEnclosedAlphanumerics}&&\p{So}]])) \d => \p{Nd} \D => \P{Nd} \R => (?:(?>\u000D\u000A)|[\u000A\u000B\u000C\u000D\u0085\u2028\u2029]) \X => (?>\PM\pM*) 

कुछ बातों पर विचार करने के लिए …

  • यह इसकी \X परिभाषा के लिए उपयोग करता है जो कि यूनिकोड को अब लीगेसी ग्राफियम क्लस्टर के रूप में संदर्भित करता है , विस्तारित ग्रैपीम क्लस्टर नहीं , जैसा कि बाद वाला अधिक जटिल है पर्ल खुद अब काल्पनिक संस्करण का उपयोग करता है, लेकिन पुराने संस्करण अभी भी सबसे आम स्थितियों के लिए पूरी तरह से उपयोगी है संपादित करें: तल पर परिशिष्ट देखें

  • के बारे में क्या करना है \d आपके इरादे पर निर्भर करता है, लेकिन डिफ़ॉल्ट यूनीड परिभाषा है मैं देख सकता हूं कि लोगों को हमेशा \p{Nd} , लेकिन कभी-कभी [0-9] या \pN

  • दो सीमा परिभाषाएं, \b और \B , विशेष रूप से \w परिभाषा का उपयोग करने के लिए लिखी गई हैं।

  • यह परिभाषा अत्यधिक व्यापक है, क्योंकि यह कैरेन्डेड अक्षरों को पकड़ लेती है, न कि केवल सर्कड वाले हैं यूनिकोड Other_Alphabetic संपत्ति Other_Alphabetic तक उपलब्ध नहीं है, इसलिए आप सबसे अच्छा कर सकते हैं।


सीमाओं की खोज

लैरी वॉल ने पहली बार 1 9 87 में पर्ल 1.0 के लिए उनके बारे में बात करने के लिए \b और \B वाक्यविन्यास के बाद सीमाएं एक समस्या हुई हैं। यह समझने की कुंजी कि कैसे \b और \B दोनों काम उनके बारे में दो व्यापक मिथकों को दूर करना है:

  1. वे कभी भी \w शब्द वर्णों की तलाश में हैं, कभी भी गैर-शब्द वर्णों के लिए नहीं
  2. वे विशेष रूप से स्ट्रिंग के किनारे की तलाश नहीं करते हैं।

\b सीमा का अर्थ है:

  IF does follow word THEN doesn't precede word ELSIF doesn't follow word THEN does precede word 

और ये सभी पूरी तरह से स्पष्ट रूप से परिभाषित हैं:

  • शब्द निम्न है (?<=\w)
  • पहले शब्द है (?=\w)
  • शब्द का पालन ​​नहीं करता है (?<!\w)
  • शब्द से पहले नहीं होता है (?!\w)

इसलिए, चूंकि IF-THEN regexes के रूप में एक and एड- AB एंक के रूप में एन्कोड किया गया है, एक or X|Y , और क्योंकि and अधिक से अधिक प्राथमिकता में है, यह केवल AB|CD । इसलिए प्रत्येक \b जिसका अर्थ है कि सीमा को सुरक्षित रूप से बदल दिया जा सकता है:

  (?:(?<=\w)(?!\w)|(?<!\w)(?=\w)) 

\w साथ उचित तरीके से परिभाषित।

(आप सोच सकते हैं कि यह अजीब है कि A और C घटक विपरीत होते हैं। एक संपूर्ण दुनिया में आपको AB|D लिखने में सक्षम होना चाहिए, लेकिन थोड़ी देर के लिए मैं यूनिकोड गुणों में पारस्परिक बहिष्कार विरोधाभासों का पीछा कर रहा था – मुझे लगता है कि मैं मैंने ध्यान रखा है, लेकिन मैंने मामले में सीमा में डबल हालत छोड़ दी है। इसके अलावा, अगर आपको अतिरिक्त विचार मिलते हैं तो इससे अधिक विस्तार होता है।)

\B गैर-सीमाओं के लिए, तर्क है:

  IF does follow word THEN does precede word ELSIF doesn't follow word THEN doesn't precede word 

\B सभी उदाहरणों की अनुमति देने के साथ:

  (?:(?<=\w)(?=\w)|(?<!\w)(?!\w)) 

यह वास्तव में यह है कि कैसे \b और \B व्यवहार करते हैं उनके लिए समतुल्य पैटर्न हैं

  • \b का उपयोग करके ((IF)THEN|ELSE) निर्माण होता है (?(?<=\w)(?!\w)|(?=\w))
  • \B का उपयोग करके ((IF)THEN|ELSE) निर्माण होता है (?(?=\w)(?<=\w)|(?<!\w))

लेकिन सिर्फ AB|CD साथ AB|CD ठीक है, खासकर अगर आपके रेगेक्स भाषा में सशर्त पैटर्न की कमी है- जैसे जावा ☹

मैंने एक परीक्षण सूट के साथ सभी तीन समकक्ष परिभाषाओं का उपयोग करते हुए पहले से ही सीमाओं के व्यवहार की पुष्टि की है, जो प्रति रन 110,385,408 मैचों की जांच करता है, और जिसके अनुसार मैं एक दर्जन से अलग डेटा कॉन्फ़िगरेशन पर चल रहा हूं:

  0 .. 7F the ASCII range 80 .. FF the non-ASCII Latin1 range 100 .. FFFF the non-Latin1 BMP (Basic Multilingual Plane) range 10000 .. 10FFFF the non-BMP portion of Unicode (the "astral" planes) 

हालांकि, लोग अक्सर एक अलग प्रकार की सीमा चाहते हैं वे कुछ चाहते हैं जो सफेद स्थान और किनारे की स्ट्रिंग को जानते हैं:

  • बाएं किनारे के रूप में (?:(?<=^)|(?<=\s))
  • सही किनारे (?=$|\s)

जावा के साथ जावा को फिक्स करना

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

यह आपको तार्किक कोड बिंदुओं में यूनिकोड वर्णों को निर्दिष्ट करने की अनुमति भी देता है, नहीं, बेवकूफ UTF-16 surrogates में। यह कठिन है कि यह कितना ज़रूरी है! और यह सिर्फ स्ट्रिंग विस्तार के लिए है

रेगेक्स चार्क्लेस प्रतिस्थापन के लिए जो आपके जावा रेगेक्स में चार्क्लास को अंततः यूनिकोड पर काम करता है, और सही तरीके से काम करता है, यहां से पूर्ण स्रोत को पकड़ो आप इसके साथ ऐसा कर सकते हैं जैसे आप कृपया, बिल्कुल। यदि आप इसे सुधारते हैं, तो मुझे इसकी सुनना अच्छा लगेगा, लेकिन आपको ऐसा करने की ज़रूरत नहीं है यह बहुत कम है मुख्य regex पुनर्लेखन समारोह की हिम्मत सरल है:

 switch (code_point) { case 'b': newstr.append(boundary); break; /* switch */ case 'B': newstr.append(not_boundary); break; /* switch */ case 'd': newstr.append(digits_charclass); break; /* switch */ case 'D': newstr.append(not_digits_charclass); break; /* switch */ case 'h': newstr.append(horizontal_whitespace_charclass); break; /* switch */ case 'H': newstr.append(not_horizontal_whitespace_charclass); break; /* switch */ case 'v': newstr.append(vertical_whitespace_charclass); break; /* switch */ case 'V': newstr.append(not_vertical_whitespace_charclass); break; /* switch */ case 'R': newstr.append(linebreak); break; /* switch */ case 's': newstr.append(whitespace_charclass); break; /* switch */ case 'S': newstr.append(not_whitespace_charclass); break; /* switch */ case 'w': newstr.append(identifier_charclass); break; /* switch */ case 'W': newstr.append(not_identifier_charclass); break; /* switch */ case 'X': newstr.append(legacy_grapheme_cluster); break; /* switch */ default: newstr.append('\\'); newstr.append(Character.toChars(code_point)); break; /* switch */ } saw_backslash = false; 

वैसे भी, यह कोड सिर्फ एक अल्फा रिलीज है, सामान मैं सप्ताहांत में ऊपर हैक कर दिया यह उस तरह से नहीं रहेगा

बीटा के लिए मेरा इरादा है:

  • कोड दोहराव एक साथ गुना

  • अनजान स्ट्रिंग पलायन के विरुद्ध एक स्पष्ट इंटरफ़ेस उपलब्ध कराएं जिससे कि रिगेक्स पलायन को बढ़ाया जा सकता है

  • \d विस्तार में कुछ लचीलेपन प्रदान करें, और शायद \b

  • सुविधा के तरीके प्रदान करें जो आपके आसपास बदलकर और Pattern.compile या String.matches या आप के लिए whatnot फोन कर रहे हैं

उत्पादन रिलीज के लिए, इसमें जवाडोक और एक जेयूनेट टेस्ट स्यूट होना चाहिए। मैं अपना गीगाटस्टर शामिल कर सकता हूं, लेकिन इसे ज्यूनेट टेस्ट के रूप में नहीं लिखा गया है।


परिशिष्ट

मेरे पास अच्छी खबर भी और बुरी खबर भी है।

अच्छी खबर यह है कि मुझे एक बेहतर \X लिए उपयोग करने के लिए एक विस्तारित ग्रैपमेस्टर क्लस्टर के लिए एक बहुत करीब सन्निकटन मिला है।

बुरी खबर यह है कि यह पैटर्न है:

 (?:(?:\u000D\u000A)|(?:[\u0E40\u0E41\u0E42\u0E43\u0E44\u0EC0\u0EC1\u0EC2\u0EC3\u0EC4\uAAB5\uAAB6\uAAB9\uAABB\uAABC]*(?:[\u1100-\u115F\uA960-\uA97C]+|([\u1100-\u115F\uA960-\uA97C]*((?:[[\u1160-\u11A2\uD7B0-\uD7C6][\uAC00\uAC1C\uAC38]][\u1160-\u11A2\uD7B0-\uD7C6]*|[\uAC01\uAC02\uAC03\uAC04])[\u11A8-\u11F9\uD7CB-\uD7FB]*))|[\u11A8-\u11F9\uD7CB-\uD7FB]+|[^[\p{Zl}\p{Zp}\p{Cc}\p{Cf}&&[^\u000D\u000A\u200C\u200D]]\u000D\u000A])[[\p{Mn}\p{Me}\u200C\u200D\u0488\u0489\u20DD\u20DE\u20DF\u20E0\u20E2\u20E3\u20E4\uA670\uA671\uA672\uFF9E\uFF9F][\p{Mc}\u0E30\u0E32\u0E33\u0E45\u0EB0\u0EB2\u0EB3]]*)|(?s:.)) 

जो जावा में आप लिखते हैं:

 String extended_grapheme_cluster = "(?:(?:\\u000D\\u000A)|(?:[\\u0E40\\u0E41\\u0E42\\u0E43\\u0E44\\u0EC0\\u0EC1\\u0EC2\\u0EC3\\u0EC4\\uAAB5\\uAAB6\\uAAB9\\uAABB\\uAABC]*(?:[\\u1100-\\u115F\\uA960-\\uA97C]+|([\\u1100-\\u115F\\uA960-\\uA97C]*((?:[[\\u1160-\\u11A2\\uD7B0-\\uD7C6][\\uAC00\\uAC1C\\uAC38]][\\u1160-\\u11A2\\uD7B0-\\uD7C6]*|[\\uAC01\\uAC02\\uAC03\\uAC04])[\\u11A8-\\u11F9\\uD7CB-\\uD7FB]*))|[\\u11A8-\\u11F9\\uD7CB-\\uD7FB]+|[^[\\p{Zl}\\p{Zp}\\p{Cc}\\p{Cf}&&[^\\u000D\\u000A\\u200C\\u200D]]\\u000D\\u000A])[[\\p{Mn}\\p{Me}\\u200C\\u200D\\u0488\\u0489\\u20DD\\u20DE\\u20DF\\u20E0\\u20E2\\u20E3\\u20E4\\uA670\\uA671\\uA672\\uFF9E\\uFF9F][\\p{Mc}\\u0E30\\u0E32\\u0E33\\u0E45\\u0EB0\\u0EB2\\u0EB3]]*)|(?s:.))"; 

¡Tschüss!

यह वाकई दुर्भाग्यपूर्ण है कि \w काम नहीं करता है प्रस्तावित समाधान \p{Alpha} मेरे लिए भी काम नहीं करता है

ऐसा लगता है कि [\p{L}] सभी यूनिकोड पत्रों को पकड़ता है इसलिए \w के यूनिकोड समकक्ष [\p{L}\p{Digit}_] होनी चाहिए।

जावा में, \w और \d युनिकोड-जागरूक नहीं हैं; वे केवल एएससीआईआई वर्णों से मेल खाते हैं, [A-Za-z0-9_] और [0-9] वही \p{Alpha} लिए जाता है और दोस्तों (वे जो POSIX "वर्ण वर्गों" पर आधारित हैं वे लोकेल-संवेदनशील होते हैं, लेकिन जावा में वे केवल एएससीआईआई अक्षर से मेल खाते हैं)। यदि आप यूनिकोड "वर्ड कैरेक्टर" से मेल खाना चाहते हैं तो आपको इसे स्पेल आउट करना होगा, जैसे [\pL\p{Mn}\p{Nd}\p{Pc}] , अक्षरों के लिए, गैर-स्पेसिंग संशोधक (एक्सेंट) दशमलव अंक, और विराम चिह्न जोड़ने।

हालांकि, जावा का \b यूनिकोड-प्रेमी है; यह Character.isLetterOrDigit(ch) का उपयोग करता है और साथ ही साथ उच्चारण अक्षर के लिए जांच करता है, लेकिन केवल "कनेक्टिंग विराम चिह्न" चरित्र को पहचानता है वह अंडरस्कोर है। संपादित करें: जब मैं अपना नमूना कोड élève" , तो यह "" और élève" रूप में प्रिंट करता है ( इसे ideone.com पर देखें )।