JavaRush /وبلاگ جاوا /Random-FA /عبارات منظم در جاوا، قسمت 3

عبارات منظم در جاوا، قسمت 3

در گروه منتشر شد
ترجمه‌ای از راهنمای کوتاه برای عبارات منظم در جاوا را که توسط جف فریسن برای وب‌سایت javaworld نوشته شده است، به اطلاع شما می‌رسانیم . برای سهولت در مطالعه مقاله را به چند قسمت تقسیم کرده ایم. عبارات منظم در جاوا، قسمت 3 - 1عبارات منظم در جاوا، قسمت 1 عبارات با قاعده در جاوا، قسمت 2

کارهای برنامه نویسی رایج را با Regex API ساده کنید

در قسمت های 1 و 2 این مقاله با عبارات منظم و Regex API آشنا شدید. شما در مورد کلاس یاد گرفتید Patternو نمونه‌هایی را که ساختارهای عبارت منظم را نشان می‌دهند، از تطبیق الگوی ساده با استفاده از رشته‌های تحت اللفظی گرفته تا تطبیق پیچیده‌تر با استفاده از محدوده‌ها، تطبیق‌کننده‌های مرزی، و کمی‌کننده‌ها را مرور کردید. در این قسمت و قسمت های بعدی به بررسی مسائلی می پردازیم که در قسمت اول به آن پرداخته نشده است، روش های مربوط به کلاس ها را مطالعه می کنیم Patternو Matcher. PatternSyntaxExceptionهمچنین دو ابزار کمکی را یاد خواهید گرفت که از عبارات منظم برای آسان کردن مشکلات رایج برنامه نویسی استفاده می کنند. اولین مورد نظرات را از کد برای مستندات استخراج می کند. دومی کتابخانه ای از کدهای قابل استفاده مجدد است که برای انجام تحلیل واژگانی طراحی شده است - جزء ضروری اسمبلرها، کامپایلرها و نرم افزارهای مشابه.

در حال بارگیری کد منبع

شما می توانید تمام کد منبع (ایجاد شده توسط Jeff Friesen برای JavaWorld) را برای برنامه های آزمایشی در این مقاله از اینجا دریافت کنید .

آموزش Regex API

Pattern، Matcherو PatternSyntaxExceptionسه کلاسی هستند که Regex API را تشکیل می دهند. هر یک از آنها روش هایی را ارائه می دهند که به شما امکان می دهد از عبارات منظم در کد خود استفاده کنید.

روش های کلاس الگو

یک نمونه از یک کلاس Patternیک عبارت منظم کامپایل شده است که به عنوان یک الگو نیز شناخته می شود. عبارات منظم برای بهبود عملکرد عملیات تطبیق الگو کامپایل می شوند. روش های استاتیک زیر از کامپایل پشتیبانی می کنند.
  • Pattern compile(String regex)محتوا را regexبه یک نمایش میانی که در یک جدید ذخیره می شود، کامپایل می کند Pattern. این متد در صورت موفقیت آمیز بودن، یا یک مرجع به یک شی برمی گرداند، یا PatternSyntaxExceptionدر صورت تشخیص نحو عبارت منظم نامعتبر، یک استثنا ایجاد می کند. هر شیء کلاسی Matcherکه توسط Patternاین شیء استفاده می شود یا از آن برگردانده می شود از تنظیمات پیش فرض خود مانند جستجوی حساس به حروف بزرگ و کوچک استفاده می کند. به عنوان مثال، قطعه کد Pattern p = Pattern.compile("(?m)^\\."); یک شی ایجاد می کند Patternکه یک نمایش کامپایل شده از یک عبارت منظم را برای مطابقت با رشته هایی که با یک کاراکتر نقطه شروع می شوند ذخیره می کند.

  • Pattern compile(String regex, int flags)همان مشکل را حل می کند Pattern compile(String regex)، اما با در نظر گرفتن flags: مجموعه ای از ثابت های بیت برای پرچم های بیت از نوع OR. کلاس Patternثابت هایی را اعلام می کند CANON_EQ, CASE_INSENSITIVE, COMMENTS, DOTALL, LITERAL, MULTILINE, UNICODE_CASE, UNICODE_CHARACTER_CLASS и UNIX_LINESکه می توانند با استفاده از OR بیتی (مثلاً CASE_INSENSITIVE | DOTALL) ترکیب شوند و به عنوان آرگومان ارسال شوند flags.

  • به استثنای CANON_EQ, LITERAL и UNICODE_CHARACTER_CLASS، این ثابت ها جایگزینی برای عبارات پرچم تودرتو هستند که در قسمت 1 نشان داده شده است. اگر ثابت پرچمی غیر از آنهایی که در کلاس تعریف شده است مواجه شود Pattern، متد Pattern compile(String regex, int flags) یک استثنا ایجاد می کند java.lang.IllegalArgumentException. به عنوان مثال، Pattern p = Pattern.compile("^\\.", Pattern.MULTILINE);معادل مثال قبلی، با Pattern.MULTILINEعبارت ثابت و پرچم تودرتو (?m)همین کار را انجام می دهند.
گاهی اوقات لازم است یک کپی از رشته اصلی یک عبارت منظم که در یک شی کامپایل شده است Pattern، همراه با پرچم هایی که استفاده می کند به دست آوریم. برای این کار می توانید روش های زیر را فراخوانی کنید:
  • String pattern()رشته عبارت منظم اصلی را که در یک کامپایل شده است برمی گرداند Pattern.

  • int flags()پرچم های شی را برمی گرداند Pattern.
پس از دریافت شی Pattern، معمولاً برای به دست آوردن شی Matcherبرای انجام عملیات تطبیق الگو استفاده می شود. این روش Matcher matcher(Charsequence input)یک شی ایجاد می کند Matcherکه متن را inputبرای مطابقت با یک الگوی شی جستجو می کند Pattern. هنگامی که فراخوانی می شود، یک مرجع به این شی برمی گرداند Matcher. به عنوان مثال، دستور برای شی مورد اشاره توسط متغیر Matcher m = p.matcher(args[1]);برمی گردد . MatcherPatternp
جستجوی یکباره
متد static boolean matches(String regex, CharSequence input)کلاس Patternبه شما امکان می دهد در ایجاد اشیاء Patternو Matcherجستجوی یکباره با استفاده از یک الگو صرفه جویی کنید. این متد اگر inputالگو مطابقت داشته باشد true را برمی‌گرداند regex، در غیر این صورت false را برمی‌گرداند. اگر عبارت منظم حاوی یک خطای نحوی باشد، متد یک استثنا ایجاد می کند PatternSyntaxException. به عنوان مثال، System.out.println(Pattern.matches("[a-z[\\s]]*", "all lowercase letters and whitespace only"));چاپ می کند trueو تأیید می کند که عبارت all lowercase letters and whitespace onlyفقط حاوی فاصله و نویسه های کوچک است.
عبارات منظم در جاوا، قسمت 3 - 2

تقسیم متن

اکثر توسعه دهندگان حداقل یک بار کد نوشته اند تا متن ورودی را به اجزای سازنده آن تقسیم کنند، مانند تبدیل یک حساب کارمند مبتنی بر متن به مجموعه ای از فیلدها. این کلاس Patternتوانایی حل راحت تر این کار خسته کننده را با استفاده از دو روش تقسیم متن فراهم می کند:
  • این متد با توجه به مطابقت های یافت شده با الگوی شی String[] split(CharSequence text, int limit)تقسیم می شود و نتایج را در یک آرایه برمی گرداند. هر عنصر آرایه یک دنباله متن را مشخص می کند که با یک قطعه متن مطابق با الگو (یا انتهای متن) از دنباله بعدی جدا شده است. عناصر آرایه به همان ترتیبی هستند که در ظاهر می شوند .textPatterntext

    در این روش، تعداد عناصر آرایه به پارامتر بستگی دارد limit، که تعداد موارد منطبق را نیز کنترل می کند.

    • یک مقدار مثبت بیشتر از limit-1موارد منطبق را جستجو نمی کند و طول آرایه بیشتر از limitعناصر نیست.
    • اگر مقدار منفی باشد، تمام مطابقت های ممکن جستجو می شود و طول آرایه می تواند دلخواه باشد.
    • اگر مقدار صفر باشد، تمام تطابق‌های ممکن جستجو می‌شوند، طول آرایه می‌تواند دلخواه باشد و خطوط خالی در انتها کنار گذاشته می‌شوند.

  • متد String[] split(CharSequence text)متد قبلی را با 0 به عنوان آرگومان حدی فراخوانی می کند و نتیجه فراخوانی خود را برمی گرداند.
در زیر نتایج روش split(CharSequence text)حل مشکل تقسیم حساب کارمند به فیلدهای جداگانه نام، سن، آدرس پستی و حقوق آمده است:
Pattern p = Pattern.compile(",\\s");
String[] fields = p.split("John Doe, 47, Hillsboro Road, 32000");
for (int i = 0; i < fields.length; i++)
   System.out.println(fields[i]);
کد بالا یک عبارت منظم را برای یافتن یک کاراکتر کاما و بلافاصله پس از آن یک کاراکتر فاصله توضیح می دهد. نتایج اجرای آن به شرح زیر است:
John Doe
47
Hillsboro Road
32000

محمولات الگو و API Streams

در جاوا 8، Patternمتدی در کلاس ظاهر شد . این روش یک گزاره (یک تابع با مقدار بولی) ایجاد می کند که برای مطابقت با الگو استفاده می شود. استفاده از این روش در قطعه کد زیر نشان داده شده است: Predicate asPredicate()
List progLangs = Arrays.asList("apl", "basic", "c", "c++", "c#", "cobol", "java", "javascript", "perl", "python", "scala");
Pattern p = Pattern.compile("^c");
progLangs.stream().filter(p.asPredicate()).forEach(System.out::println);
این کد فهرستی از نام‌های زبان‌های برنامه‌نویسی ایجاد می‌کند، سپس الگویی را برای یافتن همه نام‌هایی که با حرف شروع می‌شوند کامپایل می‌کند c. آخرین خط کد بالا دریافت یک جریان سریالی از داده ها را با این لیست به عنوان منبع اجرا می کند. با استفاده از یک تابع Boolean فیلتری را تنظیم می‌کند asPredicate()که وقتی نام با یک حرف شروع می‌شود cو در جریان تکرار می‌شود، true را برمی‌گرداند و نام‌های مطابق با خروجی استاندارد را چاپ می‌کند. این خط آخر معادل حلقه معمولی زیر است که از برنامه RegexDemo از قسمت 1 آشناست:
for (String progLang: progLangs)
   if (p.matcher(progLang).find())
      System.out.println(progLang);

روش های کلاس مطابقت

نمونه ای از کلاس Matcherمکانیزمی را برای انجام عملیات تطبیق الگو بر روی دنباله ای از کاراکترها با تفسیر عبارت منظم کامپایل شده کلاس توصیف می کند Pattern. اشیاء کلاس Matcherانواع مختلفی از عملیات جستجوی الگو را پشتیبانی می کنند:
  • این روش boolean find()متن ورودی را برای مطابقت بعدی جستجو می کند. این روش اسکن را یا در ابتدای متن مشخص شده یا در اولین کاراکتر پس از مطابقت قبلی آغاز می کند. گزینه دوم تنها در صورتی امکان پذیر است که فراخوانی قبلی به این متد به درستی برگردانده شده باشد و رزولور بازنشانی نشده باشد. در هر صورت، در صورت موفقیت آمیز بودن جستجو، مقدار بولی true برگردانده می شود. نمونه ای از این روش را می توان در قسمت 1 یافت RegexDemo.

  • این روش boolean find(int start)تطبیق دهنده را بازنشانی می کند و متن را برای مطابقت بعدی جستجو می کند. مشاهده از موقعیت مشخص شده توسط پارامتر شروع می شود start. اگر جستجو موفقیت آمیز باشد، مقدار بولی true برگردانده می شود. به عنوان مثال، m.find(1);متن را با شروع از موقعیت اسکن می کند 1(موقعیت 0 نادیده گرفته می شود). اگر پارامتر startحاوی مقدار منفی یا مقداری بزرگتر از طول متن تطبیق کننده باشد، متد یک استثنا ایجاد می کند java.lang.IndexOutOfBoundsException.

  • این روش boolean matches()تلاش می کند تمام متن را با یک الگو مطابقت دهد. اگر تمام متن با الگو مطابقت داشته باشد، مقدار بولی true را برمی‌گرداند. به عنوان مثال، کد Pattern p = Pattern.compile("\\w*"); Matcher m = p.matcher("abc!"); System.out.println(p.matches());خروجی falseبه این دلیل است که کاراکتر !یک کاراکتر کلمه نیست.

  • این روش boolean lookingAt()سعی می کند متن مشخص شده را با الگو مطابقت دهد. اگر هر قسمت از متن با الگو مطابقت داشته باشد، این روش مقدار true را برمی گرداند. برخلاف متد matches();، لازم نیست تمام متن ها با الگو مطابقت داشته باشند. به عنوان مثال، از آنجایی که ابتدای متن فقط از کاراکترهای کلمه ساز تشکیل شده است، Pattern p = Pattern.compile("\\w*"); Matcher m = p.matcher("abc!"); System.out.println(p.lookingAt());خروجی خواهد داشت .trueabc!

بر خلاف اشیاء کلاس Pattern، اشیاء کلاس Matcherاطلاعات حالت را حفظ می کنند. گاهی اوقات ممکن است لازم باشد تطبیق را بازنشانی کنید تا این اطلاعات پس از پایان جستجوی الگو پاک شود. روش های زیر برای تنظیم مجدد حل کننده موجود است:
  • این روش Matcher reset()وضعیت تطبیق را بازنشانی می کند، از جمله موقعیتی که باید به انتها اضافه شود (بازنشانی به 0). عملیات جستجوی الگوی بعدی از ابتدای متن مطابقت شروع می شود. مرجعی را به شی فعلی برمی گرداند Matcher. برای مثال، m.reset();حل‌کننده ارجاع‌شده توسط را بازنشانی می‌کند m.

  • این روش Matcher reset(CharSequence text)وضعیت حل‌کننده را بازنشانی می‌کند و متن حل‌کننده جدید را روی text. عملیات جستجوی الگوی بعدی در ابتدای متن تطبیق جدید آغاز می شود. مرجعی را به شی فعلی برمی گرداند Matcher. به عنوان مثال، m.reset("new text");حل کننده ارجاع شده را بازنشانی می کند mو متن حل کننده جدید را روی "new text".

عبارات منظم در جاوا، قسمت 3 - 3

اضافه کردن متن به پایان

موقعیت تطبیق دهنده که باید به انتها اضافه شود، آغاز متن تطبیق دهنده را که به انتهای شیء نوع الحاق می شود، مشخص می کند java.lang.StringBuffer. روش های زیر از این موقعیت استفاده می کنند:
  • این متد Matcher appendReplacement(StringBuffer sb, String replacement)کاراکترهای متن تطبیق را می خواند و آنها را به انتهای شیء StringBufferارجاع شده توسط آرگومان اضافه می کند sb. این روش خواندن را در آخرین کاراکتر قبل از مطابقت الگوی قبلی متوقف می کند. در مرحله بعد، این روش کاراکترهایی را از شی نوع Stringمورد اشاره توسط آرگومان replacementبه انتهای شی اضافه می‌کند StringBuffer(رشته replacementممکن است حاوی ارجاعاتی به دنباله‌های متنی باشد که در جستجوی قبلی گرفته شده‌اند؛ این کاراکترها با استفاده از کاراکترها ($)و اعداد گروهی که ضبط می‌شوند مشخص می‌شوند). در نهایت، این روش مقدار موقعیت تطبیق را تنظیم می کند تا به موقعیت آخرین کاراکتر تطبیق شده به اضافه یک اضافه شود و سپس یک مرجع به تطبیق فعلی برمی گرداند.

  • اگر تطبیق‌دهنده هنوز مطابقت را پیدا نکرده باشد یا تلاش قبلی برای جستجو شکست بخورد، این روش Matcher appendReplacement(StringBuffer sb, String replacement)استثنا می‌کند . اگر خط یک گروه ضبط را مشخص کند که در الگو نیست، java.lang.IllegalStateExceptionیک استثنا ایجاد می کند .IndexOutOfBoundsExceptionreplacement

  • این متد StringBuffer appendTail(StringBuffer sb)تمام متن را به یک شی اضافه می کند StringBufferو یک مرجع به آن شی برمی گرداند. پس از آخرین فراخوانی متد appendReplacement(StringBuffer sb, String replacement)، متد را فراخوانی کنید appendTail(StringBuffer sb)تا متن باقیمانده در شیء کپی شود StringBuffer.

گروه های اسیر شده
همانطور که از قسمت 1 به یاد دارید، یک گروه ضبط دنباله ای از کاراکترهای محصور در پرانتز ( ()) است. هدف از این ساختار ذخیره کاراکترهای یافت شده برای استفاده مجدد بعدی در طول تطبیق الگو است. همه کاراکترهای گروه گرفته شده به عنوان یک کل واحد در طول جستجوی الگو در نظر گرفته می شوند.
کد زیر متدهای appendReplacement(StringBuffer sb, String replacement)و را فراخوانی می‌کند appendTail(StringBuffer sbتا همه رخدادهای دنباله کاراکتر در متن مبدأ catرا با caterpillar:
Pattern p = Pattern.compile("(cat)");
Matcher m = p.matcher("one cat, two cats, or three cats on a fence");
StringBuffer sb = new StringBuffer();
while (m.find())
   m.appendReplacement(sb, "$1erpillar");
m.appendTail(sb);
System.out.println(sb);
استفاده از یک گروه ضبط شده و ارجاع به آن در متن جایگزین، به برنامه می‌گوید که erpillarپس از هر بار وقوع cat. نتیجه اجرای این کد به صورت زیر است: one caterpillar, two caterpillars, or three caterpillars on a fence

جایگزین کردن متن

کلاس Matcherدو روش برای جایگزینی متن در اختیار ما قرار می دهد که مکمل appendReplacement(StringBuffer sb, String replacement). با استفاده از این روش‌ها، می‌توانید اولین رخداد [متن جایگزین شده] یا همه رخدادها را جایگزین کنید:
  • این روش String replaceFirst(String replacement)تطبیق را بازنشانی می کند، یک شی جدید ایجاد می کند String، تمام کاراکترهای متن تطبیق دهنده (تا اولین تطابق) را در این رشته کپی می کند، کاراکترها را از انتهای آن اضافه می کند replacement، کاراکترهای باقی مانده را به رشته کپی می کند و یک عدد را برمی گرداند. شی String(رشته replacementمی تواند حاوی ارجاعاتی به مواردی باشد که در طول دنباله های متن جستجوی قبلی با استفاده از نمادهای دلار و اعداد گروه گرفته شده گرفته شده است).

  • این روش String replaceAll(String replacement)مشابه متد عمل می کند String replaceFirst(String replacement)، اما replacementهمه موارد منطبق را با کاراکترهای رشته جایگزین می کند.

یک عبارت منظم \s+یک یا چند کاراکتر فضای خالی را در متن ورودی جستجو می کند. در زیر، از این عبارت منظم استفاده می کنیم و متدی را replaceAll(String replacement)برای حذف فضاهای تکراری فراخوانی می کنیم:
Pattern p = Pattern.compile("\\s+");
Matcher m = p.matcher("Удаляем      \t\t лишние пробелы.   ");
System.out.println(m.replaceAll(" "));
در اینجا نتایج آمده است: Удаляем лишние пробелы. عبارات منظم در جاوا، قسمت 4 عبارات با قاعده در جاوا، قسمت 5
نظرات
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION