رتبه موضوع:
  • 1 رای - 5 میانگین
  • 1
  • 2
  • 3
  • 4
  • 5
آموزش عبارات باقاعده Regular Expressions
#1
خیلی از کسانی که به امر برنامه‌نویسی مشغول هستن، توی کار با عبارات باقاعده یا حتی درک ساختار و کاربردش مشکلات جدی دارن. برای همین تصمیم گرفتم این ابزار سودمند و کاربردی رو آموزش بدم. برای آموزش هم از زبان محبوب Java استفاده کردم ولی اصول الگوها و... که در اینجا میگم، در تمام زبانها یکیه و فقط توابع و ساختار زبان مربوطه ممکنه فرق کنه. بنابراین به مشکل خاصی برخورد نخواهید کرد.

این تاپیک دنباله‌دار هست و به‌مرور تکمیل میشه. پس دنبالش کنید تا این ابزار بسیار مفید و مهم رو یاد بگیرین.

توی این آموزش، یاد میگیرین که:
  • عبارات باقاعده چی هستن؟
  • چطور عبارات باقاعده بسازیم؟
  • چطور از متدهای مفید کلاس String برای انجام عملیات روی Regular Expression برای پیداکردن الگوی خاص و جایگزینی اون استفاده کنیم؟
  • کلاس Pattern چطور عبارات باقاعده رو کامپایل میکنه؟
  • روش استفاده از کلاس Matcher برای تطبیق یه الگوی خاص در متن ورودی چیه؟
  • چطور گروه‌ها رو در عبارات باقاعده بکار ببریم؟
  • روش انجام جستجو و جایگزینی پیشرفته با استفاده از کلاس Matcher چیه؟
تشکر شده توسط: habibvafapour , baghbani
#2
عبارات باقاعده چی هستن؟
یه عبارت باقاعده، روشی برای توصیف یه الگو درقالب مجموعه‌ای از کارکترهاست. این الگو میتونه برای اعتبارسنجی یکسری کارکتر، جستجو داخل یه رشته، جایگزینی یه رشته که با الگو مطابقت داره، با یه رشته‌ی دیگه و... بکار بره.

اجازه‌بدین با یه مثال شروع کنیم. فرض‌کنین یه رشته دارین که میتونه حاوی آدرس ایمیل باشه. چطور میخواین مطمئن بشین که یه آدرس ایمیل معتبر وارد شده؟ در اینجا نمیخوایم درمورد وجود اون آدرس ایمیل صحبت کنیم و فقط هدفمون اعتبارسنجی قالب ایمیل واردشده است.

ممکنه بخواین متن رو با یکسری قوانین، اعتبارسنجی کنین. برای مثال باید حتماً شامل کارکتر @ باشه که قبلش حداقل یک کارکتر اومده و بعدش هم یه اسم دامنه قید شده. بعلاوه ممکنه بخواین بگین که متن قبل از @ باید فقط شامل حروف، ارقام، کارکتر Underscore و خط‌فاصله باشه. اسم دامنه باید شامل کارکتر نقطه باشه. همچنین ممکنه بخواین یکسری اعتبارسنجی دیگه هم اضافه کنین. اگه بخواین فقط وجود کارکتر @ رو چک کنین، میشه از دستور email.indexOf('@'); استفاده کنین که email اسم متغیر ارجاعی شماست که آدرس ایمیل داخلش ذخیره شده. اگه بخواین مطمئن‌بشین که حداکثر فقط یک کارکتر @ وجود داره، باید منطق بیشتری به کدتون اضافه کنین. در چنین مواردی، درنهایت با 20 تا 50 خط کد (یا حتی بیشتر برحسب تعداد اعتبارسنجی‌های موردنظرتون) مواجه میشین. اینجا دقیقاً جایی هست که عبارات باقاعده بکار میان و به شما کمک میکنن اعتبارسنجی ایمیلتون رو به‌شکل ساده‌تری انجام بدین. میتونین تمام این کارها رو فقط با یک‌خط کد انجام بدین. اگه این موضوع صحت داشته باشه، خیلی خوبه اینطور نیست؟ یکم جلوتر گفتم که شما نیاز به 50 خط کد دارین و الان دارم میگم که فقط با یک خط کد میشه این‌کار رو انجام داد. این حقیقت‌داره. میشه فقط با یک خط کد اعتبارسنجی رو انجام بدین. قبل‌از اینکه وارد جزئیات نحوه‌ی انجام این‌کار بشم، بذارین مراحلی که برای انجام این‌کار لازمه انجام بدیم رو مرور کنیم:
  • برای اعتبارسنجی این قبیل رشته‌ها، نیاز به تشخیص الگویی داریم که به‌دنبالش هستیم. برای مثال، در ساده‌ترین حالت اعتبارسنجی یه ایمیل ، متن باید شامل یکسری کارکتر و بعدش کارکتر @ باشه که در ادامه هم آدرس یه دامنه ذکر شده. فعلاً اجازه‌بدین جزئیات دیگه رو نادیده بگیریم.
  • لازمه روشی برای توصیف الگوی تشخیص‌داده‌شده پیدا کنیم. یه عبارات باقاعده یا Regular Expression برای توصیف چنین الگویی بکار میره.
  • نیاز به برنامه‌ای داریم که بتونه الگو رو روی متن ورودی بررسی کنه و مطابقتش رو تشخیص بده. به چنین برنامه‌ای اصطلاحاً موتور عبارت باقاعده هم میگن.
فرض‌کنید که میخوایم تست کنیم که متن ما در قالب X@X هست یا نه (که X میتونه هر کارکتری باشه). رشته‌های "a@a" و "b@f" و "3@h" در این قالب هستن. الگوی موردنظر ما «یک کارکتر و بعد @ و بعد یک کارکتر دیگه» هست. چطور این الگو رو در جاوا بیان کنیم؟

رشته‌ی ".@." بیانگر عبارت باقاعده‌ی موردنظر ما برای توصیف این الگو هست. توی رشته‌ی ".@." نقطه‌ها معنای خاصی دارن و بیانگر هر کارکتری هستن. تمام کارکترهایی که معنای خاصی داخل یه عبارت باقاعده دارن، به‌اسم Meta Character شناخته میشن. درمورد متاکارکترها بعداً بیشتر توضیح میدم. کلاس String شامل یه متد به‌اسم matches() هست. این متد یه عبارت باقاعده رو بعنوان پارامتر میگیره و اگه متنی که این متد رو روی اون صدا زدیم، با الگوی موردنظر مطابقت داشته باشه، نتیجه‌ی true میده و درغیر اینصورت نتیجه‌ی false تولید خواهد شد. دستورزبان این متد به‌این‌شکله:
boolean matches(String regex)

به این مثال دقت کنید:
String regex = ".@.";
"a@k".matches(regex); // true
"webmaster@ncis.ir".matches(regex); // false
"r@j".matches(regex); // true
"a%N".matches(regex); // false
".@.".matches(regex); // true

به این نکات دقت‌کنید:
  • عبارت باقاعده‌ی ".@." با متن webmaster@ncis.ir مطابقت پیدا نمیکنه چون یک نقطه فقط معادل یک کارکتره و متد String.matches() عبارت باقاعده رو روی کل متن مورد بررسی قرار میده. درسته که الگوی ".@." توی متن وجود داره (با قسمت r@n مطابقت داره) ولی با کل متن مطابقت نداره چون توی متن ما، چند کارکتر قبل از @ و چند کارکتر بعد از اون وجود داره. درمورد الگوهایی که با بخشی از متن مطابقت پیدا میکنن بعداً چند مثال میزنم.
  • اگه بخواین خود کارکتر نقطه رو مورد بررسی قرار بدین، باید اون رو خنثی کنین تا از معنای ویژه‌ی خودش خارج بشه. برای خنثی‌کردن یه کارکتر ویژه یا همون متاکارکتر، باید قبلش یه بک‌اسلش بگذاریم و از اونجا که خود این کارکتر توی رشته‌ها معنای خاصی داره، خودش رو هم با یه بک‌اسلش دیگه خنثی میکنیم. بنابراین اگه فرضاً بخوایم متنی با سه کارکتر رو بررسی کنیم که کارکتر وسطش نقطه است، باید از الگوی [ltr".\.."[/ltr] استفاده کنیم.
همچنین میتونیم از متدهای replaceAll و replaceFirst برای جایگزین‌کردن یک متن با متن دیگه استفاده کنیم. این متدها که توی کلاس String هستن، دستورزبانی به‌این‌شکل دارن:
  • String replaceAll(String regex, String replacementString)
  • String replaceFirst(String regex, String replacementString)

متد replaceAll متن‌هایی رو که با الگوی مشخص‌شده مطابقت داشته باشن، با متن جایگزینی که تعریف کردیم جایگزین میکنه. خروجی این متد، یه رشته‌ی دیگه‌است که متن‌های موردنظر داخلش جایگزین شدن. برای مثال:
String regex = ".@.";
String newStr = "webmaster@site.com".replaceAll(regex, "***"); // webmaste***ite.com
newStr = "A@B".replaceAll(regex, "***"); // ***
newStr = "A@BandH*G".replaceAll(regex, "***"); // ***and***
newStr = "B%T".replaceAll(refex, "***"); // B%T

متن replaceFirst دقیقاً مثل متد قبلیه با این تفاوت که فقط اولین مورد مطابقت رو جایگزین میکنه نه تمام موارد پیداشده رو. بعنوان مثال:
String regex = ".@.";
String newStr = "webmaster@site.com".replaceFirst(regex, "***"); // webmaste***ite.com
newStr = "A@B".replaceFirst(regex, "***"); // ***
newStr = "A@BandH@G".replaceFirst(regex, "***"); // ***andH@G
newStr = "B%T".replaceFirst(regex, "***"); // B%T
تشکر شده توسط: habibvafapour , baghbani
#3
متاکارکترها
متاکارکترها (Metacharacters) یا کارکترهای ویژه، کارکترهایی هستن که معنای خاصی دارن. از این کارکترها در عبارات باقاعده استفاده میکنیم. گاهی‌اوقات ممکنه این کارکترهای ویژه، هیچ معنای خاصی نداشته باشن و بصورت کارکترهای عادی درنظر گرفته بشن. درواقع ویژه‌بودن این کارکترها بستگی به فضایی داره که توش مورد استفاده قرار میگیرن. متاکارکترهایی که در عبارات باقاعده کاربرد دارن اینها هستن:
  • ) پرانتز باز
  • ( پرانتز بسته
  • ] کروشه باز
  • [ کروشه بسته
  • } آکولاد باز
  • { آکولاد بسته
  • بک‌اسلش
  • ^ کَرِت (Shift+6)
  • $ کارکتر دلار
  • | میله‌ی عمودی (Shift+)
  • ? علامت سؤال
  • * ستاره (Shift+8)
  • + علامت مثبت
  • . نقطه
  • > علامت کوچکتر
  • < علامت بزرگتر
  • - خط‌فاصله یا علامت منفی
  • = علامت تساوی
  • ! علامت تعجب
تشکر شده توسط: baghbani
#4
کلاس‌های کارکتر
متاکارکترهای [ و ] (کروشه‌های باز و بسته) برای مشخص‌کردن یک کلاس کارکتر در داخل یه عبارات باقاعده بکار میرن. یه کلاس کارکتر مجموعه‌ای از کارکترهاست. موتور عبارات باقاعده سعی میکنه یکی‌از کارکترهای مجموعه رو مورد مطابقت قرار بده. دقت‌کنید که یه کلاس کارکتر هیچ ارتباطی با سازنده‌ی کلاس یا فایل‌های کلاس یا مفهوم کلاس در CSS و... نداره. کلاس کارکتر "[ABC]" با کارکترهای A و B و C مطابقت پیدا میکنه. برای مثال، رشته‌های "A@V" و "B@V" و "C@V" با عبارت باقاعده‌ی "[ABC]@." مطابقت دارن؛ درحالی‌که رشته‌ی "H@V" با این الگو مطابقت پیدا نمیکنه چون @ بعد از حروف A و B و C نیومده. بعنوان یه مثال دیگه، رشته‌های "man" و "men" با الگوی "m[ae]n" مطابقت دارن.

وقتی از اصطلاح «مطابقت» صحبت میکنم، منظورم اینه که الگو در داخل متن وجود داره. معناش این نیست که کل رشته با متن ما تطابق داره. برای مثال رشته‌ی "INFO@NCIS.IR" با الگوی "[MNO]@." مطابقت داره چون قبل‌از @ یکی‌از کارکترهای M یا N یا O قرار گرفته. همچنین رشته‌ی "A@BAND@YEA@U" هم با الگوی "[ABC]@." دوبار مطابقت داره حتی با این وجود که رشته‌ی ما شامل سه کارکتر @ هست.

شما میتونین محدوده‌ای از کارکترها رو با کمک کلاس کارکتر مشخص کنید. برای معرفی محدوده از متاکارکتر - (خط‌فاصله) استفاده میکنیم. برای مثال "[A-Z]" یه عبارت باقاعده است که تمام حروف بزرگ انگلیسی رو شامل میشه و "[0-9]" هم معادل ارقام بین 0 تا 9 هست. اگه در ابتدای یه کلاس کارکتر از متاکارکتر ^ (کَرِت) استفاده کنیم، معناش نقیض (معکوس) کلاس کارکتر موردنظره. برای مثال، "[^ABC]" به‌معنای تمام کارکترها بجز A و B و C هست. همچنین کلاس کارکتر "[^A-Z]" به‌معنای تمام کارکترها بجز حروف بزرگ الفبای انگلیسیه. اگه از کارکتر ^ هر جایی بجز ابتدای یه کلاس کارکتر استفاده کنید، معنای خاص خودش رو از دست میده و صرفاً به‌معنای خود کارکتر ^ هست. برای مثال "[ABC^]" به‌معنای کارکترهای A و B و C و ^ خواهد بود.

ضمناً شما میتونین دو یا چند محدوده رو هم داخل یه کلاس کارکتر استفاده کنید. برای مثال "a-zA-Z" به‌معنای تمام کارکترها از a تا z و از A تا Z هست. به این مثال‌ها دقت کنید:
  • [abc] کارکترهای a و b و c
  • [^xyz] هر کارکتری بجز x و y و z
  • [a-p] همه‌ی کارکترها از a تا p
  • [a-cx-z] کارکترهای a تا c و x تا z که شامل a و b و c و x و y و z میشه
  • [0-9&&[4-8]] اشتراک بین دو مجموعه (شامل 4 و 5 و 6 و 7 و 8)
  • [a-z&&[^aeiou]] تمام حروف کوچک بجز حروف صدادار. به‌عبارت دیگه، یه حرف کوچک که صدادار نباشه (تمام حروف بی‌صدای کوچک الفبای انگلیسی)

کلاس‌های کارکتر از قبل تعریف‌شده
برخی از کلاس‌های کارکتر که بیشتر از بقیه استفاده میشن، برای راحتی بیشتر، بصورت الگوهای خاصی تعریف شدن:
  • . (نقطه) هر کارکتری (میتونه شامل کارکترهای انتهای خط باشه یا نباشه که بستگی به اصلاحگرهایی داره که روی الگو تعریف میکنیم)
  • d یه رقم. مشابه [0-9]
  • D یه کارکتر غیر رقمی. مشابه [^0-9]
  • s یه کارکتر فاصله‌گذاری (Whitespace). مشابه الگوی [ tnx0Bfr] این فهرست شامل یه فاصله، یه Tab، یه New Line، یه Tab عمودی، یه کارکتر انتهای فرم و یه کارکتر رفتن به سطر بعد میشه.
  • S هر کارکتری بجز کارکترهای فاصله‌گذاری. مشابه [^s]
  • w یه کارکتر کلمه (Word). مشابه [a-zA-Z_0-9] این فهرصت شامل حروف کوچک و بزرگ الفبای انگلیسی، کارکتر خط زیر (Underscore) و ارقام مبنای 10 میشه.
  • W یه کارکتر غیر کلمه‌ای. مشابه [^w]
با اطلاعاتی که تا اینجا کسب کردیم، اگه تمام حروف کوچک و بزرگ الفبای انگلیسی، کارکتر خط‌زیر و ارقام رو در اعتبارسنجی ایمیل خودتون مجاز میدونین و حداکثر سه‌حرف برای آدرس ایمیل مدنظرتونه، عبارت باقاعده‌ی مناسب برای توصیف این الگو "w@w" خواهد بود. الان یک‌قدم در فرایند اعتبارسنجی ایمیل جلوتر رفتیم. درواقع بجای اینکه فقط کارکترهای A و B و C رو در قسمت اول ایمیل (اونطور که عبارت باقاعده‌ی [ABC]@. تعریف کرده بود)، الان هر کارکتر کلمه‌ای بعنوان قسمت اول و قسمت دوم مجازه.
تشکر شده توسط: baghbani
#5
 قدرت بیشتر در عبارات باقاعده
تا اینجا فقط سه متد از کلاس String رو برای کار با عبارات باقاعده رو دیدیم. پکیج java.util.regex شامل سه کلاس برای پشتیبانی کامل از عبارات باقاعده است. این کلاس‌ها عبارتند از:
  • Pattern
  • Matcher
  • PatternSyntaxException
یه شئ از کلاس Pattern شامل فرم کامپایل‌شده‌ی یک عبارت باقاعده است. منظورم از فرم کامپایل‌شده، نوع خاصی از عبارت باقاعده است که توی حافظه ذخیره میشه تا عملیات مطابقت رشته‌ها رو سریعتر انجام بده. یه کلاس Matcher برای مرتبط‌کردن رشته‌ای که میخوایم بررسی کنیم، با یک شئ از کلاس Pattern بکار میره و عملیات بررسی تطبیق رو بعهده داره. اشیاء کلاس PatternSyntaxException هم بیانگر خطای پیش‌آمده داخل یه عبارات باقاعده هستن که قواعد نوشتن الگوها رو رعایت نکرده.

کامپایل عبارات باقاعده
یه شئ از کلاس Pattern که برای نگهداری فرم کامپایل‌شده‌ی یک عبارت باقاعده بکار میره، غیرقابل تغییر یا Immutable هست. این کلاس، سازنده‌ی public نداره و فقط یه متد استاتیک به‌اسم compile() داره که شئ Pattern موردنظر رو برای عبارت باقاعده‌ی اعلام‌شده، برمیگردونه. این متد سربارگذاری شده:
  • static Pattern compile(String regex)
  • static Pattern compile(String regex, int flags)

به این تکه کد دقت کنید:
// Prepare a regular expression
String regex = "[a-z]@.";

// Compile the regular expression into a Pattern object
Pattern p = Pattern.compile(regex);

نسخه‌ی دوم متد compile() به شما اجازه میده یکسری پرچم (Flag) تعریف کنید که رفتار الگوی مورد مطابقت رو تغییر میده. این پرچم‌ها ماسک‌های بیتی هستن و میتونین برای ترکیبشون، اونها رو با همدیگه OR بیتی کنید (عملگر | اینکار رو انجام میده). به فهرست پرچم‌های موجود دقت کنید:
  • Pattern.CANON_EQ حالت برابری کانونی رو فعال میکنه. اگه این پرچم فعال بشه، دو کارکتر فقط درصورتی برابر هستن که تجزیه‌ی کانونی اونها با هم برابر باشه.
  • Pattern.CASE_INSENSITIVE حساسیت به بزرگی و کوچکی حروف رو از بین میبره. این حالت فقط روی کارکترهای US-ASCII کار میکنه و برای ازبین‌بردن حساسیت روی کارکترهای یونیکد، باید پرچم UNICODE_CASE رو هم با این پرچم ترکیب کنید.
  • Pattern.COMMENTS اجازه‌ی استفاده از کارکترهای فاصله‌ی خالی و توضیحات رو داخل الگو میده. وقتی این پرچم فعال بشه، کارکترهای Whitescape نادیده گرفته میشن و توضیحاتی که با # در انتهای هر خط از الگو مشخص میشن هم درنظر گرفته نخواهد شد.
  • Pattern.DOTALL حالت پشتیبانی کامل از کارکترها رو برای متاکارکتر . (نقطه) فعال میکنه. بطور پیشفرض این متاکارکتر شامل کارکترهای انتهای سطر نمیشه؛ ولی وقتی این پرچم فعال بشه، شامل کارکترهای انتهای سطر هم خواهد شد.
  • Pattern.LITERAL حالت پردازش حرفی رو فعال میکنه. وقتی این پرچم فعال بشه، کارکترهای داخل عبارت باقاعده بصورت حرفی درنظر گرفته میشن؛ یعنی متاکارکترها و کارکترهای خنثی‌سازی (Escape) هیچ معنای خاصی ندارن. البته پرچم‌های CASE_INSENSITIVE و UNICODE_CASE تأثیر خودشون رو درصورتی که با این پرچم ترکیب بشن، همچنان خواهند داشت.
  • Pattern.MULTILINE حالت چندسطری رو فعال میکنه. بطور پیشفرض متاکارکترهای ^ و $ به‌معنای ابتدا و انتهای کل متن ورودی هستن. وقتی این پرچم فعال بشه، این متاکارکترها به‌معنای ابتدا و انتهای هر سطر خواهند بود.
  • Pattern.UNICODE_CASE حالت تشخیص بزرگی و کوچکی حروف رو در کارکترهای Unicode فعال میکنه. اگه این پرچم درکنار CASE_INSENSITIVE فعال بشه، عملیات حذف حساسیت به بزرگی و کوچکی حروف برمبنای استاندارد یونیکد انجام خواهد شد.
  • Pattern.UNICODE_CHARACTER_CLASS نسخه‌ی یونیکد کلاس‌های کارکتر ازقبل تعریف‌شده و POSIX رو فعال میکنه. فعال‌کردن این پرچم تأثیر مشابه فعال‌کردن UNICODE_CASE رو هم خواهد داشت. وقتی این پرچم رو فعال کنید، کلاس‌های ازقبل تعریف‌شده (فقط US-ASCII) و همچنین کلاس‌های کارکتر POSIX، با استاندارد شماره‌ی 18 مستندات فنی یونیکد مطابقت پیدا میکنن (درمورد این استانداردها بعداً توضیح میدم).
  • Pattern.UNIX_LINES حالت خطوط لینوکس رو فعال میکنه. وقتی این پرچم فعال میشه، فقط کارکتر n بعنوان پایان خط تشخیص داده میشه.
این تکه کد نحوه‌ی کامپایل یه عبارت باقاعده رو با کمک پرچم‌های CASE_INSENSITIVE و DOTALL نشون میده. بنابراین عملیات تطبیق رشته، بدون حساسیت به بزرگی و کوچکی حروف استاندارد US-ASCII انجام میشه و متاکارکتر نقطه شامل کارکترهای انتهای سطر هم خواهد بود. برای مثال رشته‌ی "A@n" با این الگو مطابقت خواهد داشت:
// Prepare a regular expression
String regex = "[a-z]@.";

// Compile the regular expression into a Pattern object and setting
// CASE_INSENSITIVE and DOTALL flags
Pattern p = Pattern.compile(regex, Pattern.CASE_INSENSITIVE | Pattern.DOTALL);

ایجاد یک تطبیق‌دهنده
یک شئ از کلاس Matcher برای انجام بررسی مطابقت یک رشته از کارکترها با کمک الگوی کامپایل‌شده‌ای که توی یه شئ Pattern قرار گرفته، بکار میره. این کلاس هم سازنده‌ی public نداره و برای بدست‌آوردن یک شئ از این کلاس، باید از متد matcher() روی شئ Pattern موردنظر استفاده کنیم. این متد، رشته‌ای رو که میخوایم مطابقت رو روی اون مورد بررسی قرار بدیم، بعنوان پارامتر میگیره:
// Create a Pattern object
String regex = "[a-z]@.";
Pattern p = Pattern.compile(regex);

// String to perform the match
String str = "abc@yahoo.com,123@cnn.com,admin@ncis.ir";

// Get a Matcher object using Pattern object p for str
Matcher m = p.matcher(str);

در این مرحله، شئ Matcher ما یعنی m با الگوی ارائه‌شده در شئ Pattern یعنی p و متن موجود در str ارتباط پیدا کرده و الآن آماده‌ی بررسی مطابقت هستیم. معمولاً یه شئ Matcher برای پیداکردن مطابقت داخل مجموعه‌ای از کارکترها بکار میره. این مطابقت ممکنه با موفقیت انجام بشه یا اینکه رشته‌ی مربوطه با الگوی موردنظر تطبیق پیدا نکنه. اگه تطبیق انجام بشه، ممکنه دوست داشته باشین محل شروع و پایان مطابقت و همچنین بخشی از متن که با الگوی مشخص‌شده مطابقت داشته رو بدونین. میتونین از شئ Matcher درخواست کنید که همه‌ی این اطلاعات رو در اختیار شما بگذاره.

بررسی تطبیق الگو
برای اینکه از شئ Matcher بخواین عملیات مطابقت رو بررسی کنه، نیاز به استفاده از این متدها دارین:
  • متد find()
  • متد start()
  • متد end()
  • متد group()
متد find() برای پیداکردن یک مورد تطابق الگو در داخل متن موردنظر بکار میره. اگه مطابقت انجام شد، نتیجه‌ی true میده و درغیر اینصورت خروجی این متد false خواهد بود. اولین فراخوانی این متد شروع به جستجو از ابتدای متن میکنه. اگه فراخوانی قبلی این متد موفقیت‌آمیز باشه، فراخوانی مجددش باعث ادامه‌ی بررسی از محل آخرین تطابق پیداشده میشه. معمولاً فراخوانی متد find() داخل حلقه while انجام میشه تا همه‌ی موارد مطابقت رو پیدا کنیم. این متد، سربارگذاری شده. نسخه‌ی دیگری از متد find() هم وجود داره که یه عدد صحیح بعنوان پارامتر میگیره که بیانگر فاصله‌ی موردنظر از ابتدای رشته برای شروع عملیات جستجو هست.

متد start() محل شروع آخرین مطابقت رو برمیگردونه. شماره‌گذاری کارکترها از صفر شروع میشه و معمولاً این متد بعد از یک فراخوانی موفقیت‌آمیز متد find() صدا زده میشه.

متد end() برای بدست‌آوردن محل پایان مطابقت + 1 بکار میره (درواقع محل اولین کارکتر بعد از مطابقت رو برمیگردونه). بنابراین، بعد از فراخوانی موفقیت‌آمیز متد find()، تفاضل بین مقادیر خروجی start() و end() به شما طول رشته‌ای که با الگو مطابقت داشته رو برمیگردونه و باکمک متد substring() از کلاس String روی شئ مربوط به رشته‌ی موردنظر، میتونین الگوی پیداشده رو استخراج کنید:
// Continued from previous fragment of code
if (m.find()) {
    // str is the string we are looking into
    String foundStr = str.substring(m.start(), m.end() - m.start());
}

متد group() رشته‌ی پیداشده از آخرین فراخوانی موفقیت‌آمیز find() رو برمیگردونه. یادتون نره که میشه باکمک متد substring() هم اینکار رو انجام بدین و از متدهای start() و end() کمک بگیرین. بنابراین، کد بالا رو میشه اینطوری هم نوشت:
if (m.find()) {
    String foundStr = m.group();
}

حالا به این مثال دقت کنید که نحوه‌ی استفاده از این متدها رو نشون میده. اعتبارسنجی پارامترهای متدها برای سادگی و خوانایی برنامه نادیده گرفته شده. هدف از این کد، بررسی الگوی "[abc]@." داخل رشته‌های مختلفه:
public class PatternMatcher {
   public static void findPattern(String regex, String source) {
       // Compile regex into a Pattern object
       Pattern p = Pattern.compile(regex);

       // Get a Matcher object
       Matcher m = p.matcher(source);

       // Print regex and source text
       System.out.println("nRegex: " + regex);
       System.out.println("Text: " + source);

       // Perform find
       boolean found = false;
       while (m.find()) {
           System.out.println("Matched Text: " + m.group() + ", Start: " + m.start() + ", End: " + m.end());
           // We found at least one match. Set the found variable to true
           found = true;
       }

       if (!found) {
           // We did not find any match
           System.out.println("No match found");
       }
   }
}

// Usage:
String regex = "[abc]@.";

String source = "aida@gmail.com is a valid email address";
PatternMatcher.findPattern(regex, source);

source = "admin@ncis.ir";
PatternMatcher.findPattern(regex, source);

source = "a@band@yea@u";
PatternMatcher.findPattern(regex, source);

source = "There is an @ sign here";
PatternMatcher.findPattern(regex, source);

/* Output:
Regex: [abc]@.
Text: aida@gmail.com is a valid email address
Matched Text: c@j, Start: 3, End: 6

Regex: [abc]@.
Text: admin@ncis.ir
No match found

Regex: [abc]@.
Text: a@band@yea@u
Matched Text: a@b, Start: 0, End: 3
Matched Text: a@u, Start: 9, End: 12

Regex: [abc]@.
Text: There is an @ sign here
No match found
*/
تشکر شده توسط: baghbani




کاربران در حال بازدید این موضوع: 1 مهمان