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


126

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

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

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

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


3
लघुकथा, टिम, यह है कि उन सभी को यूनिकोड के अनुरूप लाने के लिए लेखन की आवश्यकता है। मुझे अभी भी कोई संकेत नहीं दिखता है कि स्क्रिप्ट के लिए समर्थन जोड़ने की तुलना में जावा 1.7 यूनिकोड गुणों के साथ कुछ और करेगा , लेकिन यह है। कुछ चीजें हैं जो आप वास्तव में यूनिकोड गुणों के पूर्ण पूरक के लिए बेहतर पहुंच के बिना नहीं कर सकते हैं। यदि आपके पास अभी तक मेरे यूनिप्रॉप्स और यूनीचर्स स्क्रिप्ट्स (और यूनिनम्स ) नहीं हैं, तो वे इस सब में आश्चर्यजनक आई-ओपनर्स हैं।
tchrist

कोई शब्द वर्ग में अंक जोड़ने पर विचार कर सकता है। उदाहरण के लिए & auml; यूनिकोड में या तो \ u0061 \ u0308 या \ u00E4 के रूप में प्रतिनिधित्व किया जा सकता है।
मोस्टोव्स्की को

3
हे टिम, मेरे अद्यतन की जाँच करें। उन्होंने यह सब काम करने के लिए एक ध्वज जोड़ा है। हुर्रे!
tchrist

जवाबों:


240

सोर्स कोड

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

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

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


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

जिसका अर्थ है - जावा regexes के साथ समस्या यह है कि पर्ल 1.0 charclass पलायन है \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गुण। यह अत्यधिक कष्टप्रद है। जावा की यूनिकोड संपत्ति का समर्थन कड़ाई से विरोधाभासी है , जिसका अर्थ है कि यह पिछले दशक में बाहर निकली कोई यूनिकोड संपत्ति का समर्थन नहीं करता है।

व्हाट्सएप के बारे में ठीक से बात नहीं कर पाना सुपर-कष्टप्रद है। निम्न तालिका पर विचार करें। उन कोड बिंदुओं में से प्रत्येक के लिए, जावा के लिए J- परिणाम स्तंभ और Perl या किसी अन्य PCRE- आधारित regex इंजन के लिए P- परिणाम स्तंभ दोनों हैं:

             Regex    001A    0085    00A0    2029
                      J  P    J  P    J  P    J  P
                \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  -

देखना है कि?

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


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

इससे संबंधित और कई अन्य समस्याओं से निपटने के लिए, कल मैंने एक पैटर्न स्ट्रिंग को फिर से लिखने के लिए एक जावा फ़ंक्शन लिखा था जो इन 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परिभाषा का उपयोग करने के लिए लिखे गए हैं ।

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


सीमाओं की खोज

सीमाएँ तब से एक समस्या है जब लैरी वॉल ने पहली बार 1987 में पर्ल 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)

इसलिए, चूंकि regexes में IF-THENएक and एड-साथ ABमें एन्कोड किया गया है , एक orहै X|Y, और क्योंकि andपूर्व की तुलना में अधिक है or, जो कि बस है 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ठीक हैं, खासकर यदि आप अपनी regex भाषा में सशर्त पैटर्न की कमी रखते हैं - जैसे जावा। ☹

मैंने पहले से ही एक परीक्षण सूट के साथ सभी तीन समान परिभाषाओं का उपयोग करते हुए सीमाओं के व्यवहार को सत्यापित किया है जो प्रति रन 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)

जावा के साथ जावा फिक्सिंग

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

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

रेगेक्स चारक्लास प्रतिस्थापन के लिए जो आपके जावा रेगेक्स में चारकल बनाता है अंत में यूनिकोड पर काम करता है, और सही ढंग से काम करता है, यहां से पूर्ण स्रोत को पकड़ो आप इसके साथ कृपया कर सकते हैं, कृपया। यदि आप इसे ठीक करते हैं, तो मुझे यह सुनना अच्छा लगेगा, लेकिन आपको ऐसा नहीं करना चाहिए। यह बहुत छोटा है। मुख्य 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 को कॉल करती हैं

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


परिशिष्ट

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

अच्छी खबर यह है कि मैं अब एक बेहतर के लिए उपयोग करने के लिए एक विस्तारित अंगूर क्लस्टर के लिए एक बहुत करीब सन्निकटन मिला है ।\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!


10
ये अद्भुत है। बहुत बहुत धन्यवाद।
टिम पीटरज़ॉक्ट

9
क्राइस्ट, वह एक आत्मज्ञानी उत्तर है। मुझे केवल जॉन स्कीट संदर्भ नहीं मिला। उसका इससे क्या लेना-देना है?
BalusC

12
@ बाल्स्क: यह जॉन के लिए एक रेफरी है जो पहले कह रहा था कि वह मुझे सवाल का जवाब देंगे। लेकिन कृपया, t@tchrist को न छोड़ें । यह मेरे सिर पर जा सकता है। :)
tchrist 1

3
क्या आपने इसे OpenJDK में जोड़ने के बारे में सोचा है?
मार्टिज़न वेरबर्ग

2
@ मार्टिज़न: मैंने नहीं, नहीं; मुझे नहीं पता था कि यह "खुला" था। :) लेकिन मैंने इसे और अधिक औपचारिक अर्थों में जारी करने के बारे में सोचा है; मेरे विभाग के अन्य लोग यह देखना चाहते हैं कि किया गया (किसी प्रकार के ओपन-सोर्स लाइसेंस, शायद बीएसडी या एएसएल के साथ)। मैं शायद इस अल्फा प्रोटोटाइप में एपीआई को बदलने जा रहा हूं, कोड को साफ करना, आदि। लेकिन यह हमें बहुत मदद करता है , और हम यह भी मदद करते हैं कि यह दूसरों को भी मदद करेगा। मैं वास्तव में कामना करता हूं कि सूर्य उनके पुस्तकालय के बारे में कुछ करे, लेकिन ओरेकल अविश्वास की प्रेरणा देता है।
tchrist

15

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

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


लेकिन \wअंकों और अधिक से मेल भी खाता है। मुझे लगता है कि सिर्फ पत्रों के लिए, \p{L}काम करेगा।
बजे टिम पीटरज़ॉव

आप सही हे। \p{L}पर्याप्त है। इसके अलावा, मुझे लगा कि केवल पत्र ही समस्या थे। [\p{L}\p{Digit}_]अंडरस्कोर सहित सभी अल्फ़ान्यूमेरिक वर्णों को पकड़ना चाहिए।
MUSIKK

@MusicKk: एक पूर्ण समाधान के लिए मेरा उत्तर देखें जो आपको अपने पैटर्न को सामान्य रूप से लिखने की अनुमति देता है, लेकिन फिर इसे एक फ़ंक्शन के माध्यम से पास करें जो जावा के अंतराल लैकुने के लिए सही करता है ताकि यह यूनिकोड पर ठीक से काम करे।
tchrist

नहीं, \wयूनिकोड द्वारा परिभाषित किया गया है कि \pLसभी मूर्खतापूर्ण चीजों की तुलना में सिर्फ और ASCII अंकों की तुलना में अधिक व्यापक है । आपको लिखना होगा [\pL\pM\p{Nd}\p{Nl}\p{Pc}[\p{InEnclosedAlphanumerics}&&\p{So}]]कि क्या आप \wजावा के लिए यूनिकोड-अवगत चाहते हैं - या आप बस यहाँunicode_charclass से मेरे फ़ंक्शन का उपयोग कर सकते हैं । माफ़ करना!
tchrist

1
@ टिम, हां, पत्रों के लिए \pLकाम करता है (आपको एक-अक्षर के अक्षरों को गले लगाने की आवश्यकता नहीं है)। हालाँकि, आप शायद ही कभी ऐसा चाहते हों, क्योंकि आपको इस बात का ध्यान रखना है कि आपके मैच के अलग-अलग जवाब न मिले, क्योंकि आपका डेटा यूनिकोड नॉर्मलाइज़ेशन फॉर्म डी (उर्फ एनएफडी, विहित विघटन ) में है, बनाम एनएफसी (एनएफडी) में विहित है। रचना )। एक उदाहरण है कि कोड बिंदु U + E9 ( "é") \pLएनएफसी फॉर्म में है, लेकिन इसका NFD फॉर्म U + 65.301 है, इसलिए मेल खाता है \pL\pM। आप कर सकते हैं थोड़े साथ इस के आसपास मिलता है \X: (?:(?=\pL)\X), लेकिन आप जावा के लिए कि की मेरी संस्करण की आवश्यकता होगी। :(
tchrist

7

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

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


मुझे क्षमा करें, एलन, लेकिन आप वास्तव में यह नहीं कह सकते कि जावा का \bयूनिकोड Al प्रेमी है। यह टन और गलतियों का टन बनाता है। "\u2163=", "\u24e7="और "\u0301="सभी "\\b="जावा में मिलान पैटर्न से विफल होते हैं, लेकिन जैसा कि पता चलता है - माना जाताperl -le 'print /\b=/ || 0 for "\x{2163}=", "\x{24e7}=", "\x{301}="' है। हालांकि, अगर (और केवल अगर) आप जावा में मूल के बजाय एक शब्द सीमा के मेरे संस्करण में स्वैप \bकरते हैं, तो वे सभी जावा में भी काम करते हैं।
tchrist

@tchrist: मैं \bकेवल शुद्धता पर टिप्पणी नहीं कर रहा था , यह इंगित करता है कि यह यूनिकोड वर्णों पर काम करता है (जैसा कि जावा में कार्यान्वित किया गया है), न कि केवल ASCII जैसे \wऔर मित्र। हालाँकि, यह सही ढंग से काम करता है \u0301जब उस चरित्र को आधार चरित्र के साथ जोड़ा जाता है, जैसे कि e\u0301=। और मुझे यकीन नहीं है कि जावा इस उदाहरण में गलत है। जब तक यह एक पत्र के साथ एक अंगूर समूह का हिस्सा नहीं है तब तक एक संयोजन चिह्न को एक शब्द चरित्र कैसे माना जा सकता है?
एलन मूर

3
@Alan, यह एक ऐसी चीज़ है जिसे यूनिकोड ने स्पष्ट किया गया है कि विस्तारित बनाम विरासत अंगूर समूहों पर चर्चा करके ग्रैफेम समूहों को स्पष्ट किया है। एक अंगूर क्लस्टर की पुरानी परिभाषा, जिसमें \Xकिसी भी संख्या के निशान के बाद एक गैर-चिह्न है, समस्याग्रस्त है, क्योंकि आपको सभी फ़ाइलों का मिलान करने में सक्षम होना चाहिए /^(\X*\R)*\R?$/, लेकिन यदि आपके पास \pMशुरुआत में नहीं है फ़ाइल, या एक पंक्ति का भी। इसलिए उन्होंने इसे हमेशा कम से कम एक चरित्र से मेल खाने के लिए तैयार किया है। यह हमेशा किया था, लेकिन अब यह उपरोक्त पैटर्न काम करता है। [… जारी रखा]
tchrist

2
@Alan, यह अच्छे से अधिक नुकसान करता है कि जावा का मूल \bआंशिक यूनिकोड-जागरूक है। "élève"पैटर्न के खिलाफ स्ट्रिंग के मिलान पर विचार करें \b(\w+)\b। समस्या देखें?
त्रिकाल

1
@ टिचर: हां, शब्द सीमा के बिना, \w+दो मैच पाते हैं: lऔर ve, जो काफी खराब है। लेकिन साथ शब्द सीमाओं यह, कुछ भी नहीं पाता है क्योंकि \bपहचानता है éऔर èशब्द पात्रों के रूप में। बहुत कम से कम, \bऔर \wइस बात पर सहमत होना चाहिए कि एक शब्द चरित्र क्या है और क्या नहीं है।
एलन मूर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.