کارهای برنامه نویسی رایج را با 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]);
برمی گردد . Matcher
Pattern
p
جستجوی یکباره |
---|
متد 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 فقط حاوی فاصله و نویسه های کوچک است. |
تقسیم متن
اکثر توسعه دهندگان حداقل یک بار کد نوشته اند تا متن ورودی را به اجزای سازنده آن تقسیم کنند، مانند تبدیل یک حساب کارمند مبتنی بر متن به مجموعه ای از فیلدها. این کلاسPattern
توانایی حل راحت تر این کار خسته کننده را با استفاده از دو روش تقسیم متن فراهم می کند:
-
این متد با توجه به مطابقت های یافت شده با الگوی شی
String[] split(CharSequence text, int limit)
تقسیم می شود و نتایج را در یک آرایه برمی گرداند. هر عنصر آرایه یک دنباله متن را مشخص می کند که با یک قطعه متن مطابق با الگو (یا انتهای متن) از دنباله بعدی جدا شده است. عناصر آرایه به همان ترتیبی هستند که در ظاهر می شوند .text
Pattern
text
در این روش، تعداد عناصر آرایه به پارامتر بستگی دارد
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());
خروجی خواهد داشت .true
abc!
Pattern
، اشیاء کلاس Matcher
اطلاعات حالت را حفظ می کنند. گاهی اوقات ممکن است لازم باشد تطبیق را بازنشانی کنید تا این اطلاعات پس از پایان جستجوی الگو پاک شود. روش های زیر برای تنظیم مجدد حل کننده موجود است:
-
این روش
Matcher reset()
وضعیت تطبیق را بازنشانی می کند، از جمله موقعیتی که باید به انتها اضافه شود (بازنشانی به 0). عملیات جستجوی الگوی بعدی از ابتدای متن مطابقت شروع می شود. مرجعی را به شی فعلی برمی گرداندMatcher
. برای مثال،m.reset();
حلکننده ارجاعشده توسط را بازنشانی میکندm
. -
این روش
Matcher reset(CharSequence text)
وضعیت حلکننده را بازنشانی میکند و متن حلکننده جدید را رویtext
. عملیات جستجوی الگوی بعدی در ابتدای متن تطبیق جدید آغاز می شود. مرجعی را به شی فعلی برمی گرداندMatcher
. به عنوان مثال،m.reset("new text");
حل کننده ارجاع شده را بازنشانی می کندm
و متن حل کننده جدید را روی"new text"
.
اضافه کردن متن به پایان
موقعیت تطبیق دهنده که باید به انتها اضافه شود، آغاز متن تطبیق دهنده را که به انتهای شیء نوع الحاق می شود، مشخص می کندjava.lang.StringBuffer
. روش های زیر از این موقعیت استفاده می کنند:
-
این متد
Matcher appendReplacement(StringBuffer sb, String replacement)
کاراکترهای متن تطبیق را می خواند و آنها را به انتهای شیءStringBuffer
ارجاع شده توسط آرگومان اضافه می کندsb
. این روش خواندن را در آخرین کاراکتر قبل از مطابقت الگوی قبلی متوقف می کند. در مرحله بعد، این روش کاراکترهایی را از شی نوعString
مورد اشاره توسط آرگومانreplacement
به انتهای شی اضافه میکندStringBuffer
(رشتهreplacement
ممکن است حاوی ارجاعاتی به دنبالههای متنی باشد که در جستجوی قبلی گرفته شدهاند؛ این کاراکترها با استفاده از کاراکترها($)
و اعداد گروهی که ضبط میشوند مشخص میشوند). در نهایت، این روش مقدار موقعیت تطبیق را تنظیم می کند تا به موقعیت آخرین کاراکتر تطبیق شده به اضافه یک اضافه شود و سپس یک مرجع به تطبیق فعلی برمی گرداند. -
این متد
StringBuffer appendTail(StringBuffer sb)
تمام متن را به یک شی اضافه می کندStringBuffer
و یک مرجع به آن شی برمی گرداند. پس از آخرین فراخوانی متدappendReplacement(StringBuffer sb, String replacement)
، متد را فراخوانی کنیدappendTail(StringBuffer sb)
تا متن باقیمانده در شیء کپی شودStringBuffer
.
اگر تطبیقدهنده هنوز مطابقت را پیدا نکرده باشد یا تلاش قبلی برای جستجو شکست بخورد، این روش Matcher appendReplacement(StringBuffer sb, String replacement)
استثنا میکند . اگر خط یک گروه ضبط را مشخص کند که در الگو نیست، java.lang.IllegalStateException
یک استثنا ایجاد می کند .IndexOutOfBoundsException
replacement
گروه های اسیر شده |
---|
همانطور که از قسمت 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
GO TO FULL VERSION