সোর্স কোড
আমি নীচে আলোচনা করে পুনরায় লেখার ফাংশনগুলির উত্স কোডটি এখানে উপলভ্য ।
জাভা 7 এ আপডেট
Pattern
জেডিকে for এর জন্য সনের আপডেট হওয়া ক্লাসে একটি দুর্দান্ত নতুন পতাকা রয়েছে UNICODE_CHARACTER_CLASS
, যা সবকিছু ঠিকঠাক করে তোলে। এটি (?U)
প্যাটার্নের অভ্যন্তরের জন্য এম্বেডেবল হিসাবে উপলব্ধ , তাই আপনি এটি String
ক্লাসের মোড়ক দিয়েও ব্যবহার করতে পারেন । এটি স্পোর্টসও অন্যান্য বিভিন্ন বৈশিষ্ট্যের সংশোধন সংজ্ঞা দেয়। এটি এখন ইউটিএস # 18 থেকে আরএল 1.2 এবং আরএল 1.2 উভয় ক্ষেত্রেই ইউনিকোড স্ট্যান্ডার্ডকে অনুসরণ করে : ইউনিকোড নিয়মিত অভিব্যক্তি । এটি একটি উত্তেজনাপূর্ণ এবং নাটকীয় উন্নতি, এবং উন্নয়ন দলকে এই গুরুত্বপূর্ণ প্রচেষ্টাটির জন্য প্রশংসা করা উচিত।
জাভার রেজেক্স ইউনিকোড সমস্যা
অর্থ - জাভা regexes সঙ্গে সমস্যা হল পার্ল 1.0 charclass বেরিয়ে হয় \w
, \b
, \s
, \d
এবং তাদের সম্পূরক সমূহ - জাভা ইউনিকোড এর সাথে কাজ করা বাড়ানো নয়। এই মধ্যে একা একা, \b
নির্দিষ্ট বর্ধিত শব্দার্থবিদ্যা ভোগ, কিন্তু এই মানচিত্র তন্ন তন্ন করতে \w
, কিংবা করতে ইউনিকোড শনাক্তকারী , কিংবা করতে ইউনিকোড লাইন বিরতি বৈশিষ্ট্য ।
অতিরিক্তভাবে, জাভাতে থাকা পসিক্স বৈশিষ্ট্যগুলি এইভাবে অ্যাক্সেস করা হয়েছে:
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
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̲। এটি সত্যিই একটি বড় সমস্যা। জাভা সবেমাত্র গণ্ডগোল করে, এমন উত্তর দেয় যা বিদ্যমান অনুশীলন অনুসারে এবং ইউনিকোড অনুসারে “ভুল”। প্লাস জাভা আপনাকে বাস্তব ইউনিকোড বৈশিষ্ট্যে অ্যাক্সেসও দেয় না! আসলে, জাভা ইউনিকোড হোয়াইটস্পেসের সাথে সম্পর্কিত এমন কোনও সম্পত্তি সমর্থন করে না ।
এই সমস্ত সমস্যার সমাধান এবং আরও অনেক কিছু
এই এবং অন্যান্য অনেক সম্পর্কিত সমস্যার সাথে মোকাবিলা করার জন্য, গতকাল আমি একটি 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_Alphabetic
সম্পত্তি জেডিকে 7 অবধি উপলব্ধ নয়, সুতরাং এটি আপনার পক্ষে সেরা।
সীমানা এক্সপ্লোর করা
১৯৮7 সালে ল্যারি ওয়াল পার্ল ১.০-এর জন্য প্রথম তাদের সম্পর্কে কথা বলার জন্য সিন্টেক্স \b
এবং \B
সিনট্যাক্স তৈরি করার পরে বাউন্ডারিগুলি একটি সমস্যা হয়ে দাঁড়িয়েছে how কীভাবে \b
এবং \B
উভয় কাজই বোঝার মূল বিষয়টি তাদের সম্পর্কে দুটি বিস্তৃত কল্পকাহিনীকে দূর করা:
- তারা হয় শুধুমাত্র কখনও খুঁজছেন জন্য
\w
শব্দ অক্ষর, কখনো অ শব্দ অক্ষরের জন্য।
- তারা স্ট্রিংয়ের প্রান্তটি বিশেষভাবে সন্ধান করে না।
একটি \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
একটি হিসাবে এনকোডেড হয়েছে and
ইডি-একসঙ্গে AB
regexes, একটি or
হল X|Y
, এবং কারণ and
প্রাধান্য বেশি চেয়ে or
, সহজভাবে যে AB|CD
। সুতরাং প্রত্যেকটির \b
অর্থ একটি সীমানা নিরাপদে প্রতিস্থাপন করা যেতে পারে:
(?:(?<=\w)(?!\w)|(?<!\w)(?=\w))
সঙ্গে \w
উপযুক্ত ভাবে সংজ্ঞায়িত।
(আপনি এটা অদ্ভুত যে মনে হতে পারে A
এবং C
উপাদান বিপরীতের হয় একটি নিখুঁত বিশ্বে, আপনি যে লিখতে সক্ষম হওয়া উচিত। AB|D
কিন্তু এর জন্য যখন আমি ইউনিকোড বৈশিষ্ট্যের মিউচুয়াল বর্জন অসঙ্গতি নিচে পশ্চাদ্ধাবন ছিল - যা আমি মনে করি আমি যত্ন গ্রহণ করেছি , তবে আমি ডাবল শর্তটি কেবল সীমানায় রেখে দিয়েছি Plus এছাড়াও পরে আপনি অতিরিক্ত ধারণা পান তবে এটি আরও প্রসারিত করে)
জন্য \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
খুব ভাল, বিশেষত আপনার জাভেজ ভাষায় শর্তসাপেক্ষ নিদর্শনগুলির অভাব যেমন জাভার মতো। ☹
আমি ইতিমধ্যে টেস্ট স্যুইটের সাথে তিনটি সমতুল্য সংজ্ঞা ব্যবহার করে বাউন্ডারের আচরণ যাচাই করেছি যা প্রতি রান প্রতি 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)
জাভা দিয়ে জাভা ঠিক করা
আমার অন্যান্য উত্তরে আমি পোস্ট করা কোডটি এটি এবং বেশ কয়েকটি অন্যান্য সুবিধাদি সরবরাহ করে। এর মধ্যে রয়েছে প্রাকৃতিক-ভাষার শব্দ, ড্যাশ, হাইফেন এবং অ্যাডোস্ট্রোফসের সংজ্ঞা এবং আরও কিছু includes
এটি আপনাকে ইউজিক্যাল ইউটিএফ -16 সারোগেটে নয়, লজিকাল কোড পয়েন্টগুলিতে ইউনিকোড অক্ষর নির্দিষ্ট করার অনুমতি দেয়। এটা কতটা গুরুত্বপূর্ণ তা বোঝা শক্ত! এবং এটি কেবল স্ট্রিং সম্প্রসারণের জন্য।
Regex charclass প্রতিকল্পন আপনার জাভা charclass তোলে regexes জন্য পরিশেষে ইউনিকোড উপর কাজ, এবং কাজের সঠিকভাবে দখল এখান থেকে পূর্ণ উৎস । আপনি অবশ্যই এটি সঙ্গে করতে পারেন, অবশ্যই। আপনি যদি এটিকে সংশোধন করেন তবে আমি এটি শুনতে খুব পছন্দ করব, তবে আপনার দরকার নেই। এটি বেশ সংক্ষিপ্ত। মূল রেজেক্স পুনর্লিখন ফাংশনের সাহসগুলি সহজ:
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;
যাইহোক, এই কোডটি কেবলমাত্র একটি আলফা রিলিজ, আমি সপ্তাহান্তে হ্যাক করেছি stuff এটি সেভাবে থাকবে না।
বিটার জন্য আমি মনস্থ করি:
কোড নকল একসাথে ভাঁজ করুন
বর্ধমান রেজেক্স পলায়নের বিপরীতে অনেস্কেপিং স্ট্রিং পলায়নের বিষয়ে একটি পরিষ্কার ইন্টারফেস সরবরাহ করুন
\d
সম্প্রসারণে কিছুটা নমনীয়তা সরবরাহ করুন এবং সম্ভবত the\b
ঘুরতে এবং প্যাটার্ন ডটকমকেলে বা স্ট্রিং.ম্যাচগুলি বা আপনার জন্য হোয়াটনট কল করার সুবিধার্থে এমন পদ্ধতি সরবরাহ করুন
উত্পাদনের মুক্তির জন্য, এতে জাভাদোক এবং একটি জুনিত পরীক্ষা স্যুট থাকতে হবে। আমি আমার জিগেটেস্টার অন্তর্ভুক্ত করতে পারি, তবে এটি JUnit পরীক্ষা হিসাবে লেখা হয় না।
অভিযোজ্য বস্তু
আমার কাছে ভাল খবর এবং খারাপ খবর আছে।
সুসংবাদটি হ'ল আমি এখন একটি বর্ধিত গ্রাফেমি ক্লাস্টারের একটি উন্নত ব্যবহারের জন্য খুব কাছাকাছি সান্নিধ্য পেয়েছি \X
।
খারাপ খবর that যে প্যাটার্নটি হ'ল:
(?:(?:\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üß!