
یک عبارت منظم (regex) چیست؟
در واقع یک عبارت منظم الگویی برای یافتن یک رشته در متن است. در جاوا، نمایش اصلی این الگو همیشه یک رشته، یعنی یک شی ازString
کلاس است. با این حال، هیچ رشته ای نیست که بتوان به یک عبارت منظم کامپایل کرد - فقط رشته هایی که با قوانین ایجاد عبارات منظم مطابقت دارند. نحو در مشخصات زبان تعریف شده است. عبارات منظم با استفاده از حروف و اعداد و همچنین متاکاراکترها نوشته می شوند که کاراکترهایی هستند که معنای خاصی در نحو عبارت منظم دارند. مثلا:
String regex = "java"; // The pattern is "java";
String regex = "\\d{3}"; // The pattern is three digits;
ایجاد عبارات منظم در جاوا
ایجاد یک عبارت منظم در جاوا شامل دو مرحله ساده است:- آن را به صورت رشته ای بنویسید که با نحو عبارت منظم مطابقت دارد.
- رشته را به یک عبارت منظم کامپایل کنید.
Pattern
شی شروع می کنیم. برای این کار باید یکی از دو متد static کلاس را فراخوانی کنیم: compile
. روش اول یک آرگومان می گیرد - یک رشته تحت اللفظی حاوی عبارت منظم، در حالی که روش دوم یک آرگومان اضافی را می گیرد که تنظیمات تطبیق الگو را تعیین می کند:
public static Pattern compile (String literal)
public static Pattern compile (String literal, int flags)
لیست مقادیر بالقوه
پارامتر flags
در کلاس تعریف شده Pattern
و به عنوان متغیرهای کلاس ایستا در دسترس ما است. مثلا:
Pattern pattern = Pattern.compile("java", Pattern.CASE_INSENSITIVE); // Pattern-matching will be case insensitive.
اساساً Pattern
کلاس سازنده ای برای عبارات منظم است. در زیر هود، compile
متد سازنده خصوصی کلاس را فراخوانی می کند Pattern
تا یک نمایش کامپایل شده ایجاد کند. این مکانیسم ایجاد شی به این روش به منظور ایجاد اشیاء تغییرناپذیر پیاده سازی می شود. هنگامی که یک عبارت منظم ایجاد می شود، نحو آن بررسی می شود. اگر رشته دارای خطا باشد، a PatternSyntaxException
ایجاد می شود.
نحو عبارت منظم
نحو بیان منظم به<([{\^-=$!|]})?*+.>
کاراکترها متکی است که می توانند با حروف ترکیب شوند. بسته به نقش آنها می توان آنها را به چند گروه تقسیم کرد:
متاکاراکتر | شرح |
---|---|
^ | ابتدای یک خط |
$ | انتهای یک خط |
\b | مرز کلمه |
\ B | مرز غیر کلمه |
\آ | ابتدای ورودی |
\G | پایان مسابقه قبلی |
\Z | انتهای ورودی |
\z | انتهای ورودی |
متاکاراکتر | شرح |
---|---|
\d | رقم |
\ D | غیر رقمی |
\s | کاراکتر فضای خالی |
\S | کاراکتر بدون فضای سفید |
\w | کاراکتر الفبایی یا زیرخط |
\ W | هر کاراکتری به جز حروف، اعداد و خط زیر |
. | هر شخصیت |
متاکاراکتر | شرح |
---|---|
\ t | کاراکتر برگه |
\n | شخصیت خط جدید |
\r | برگشت محموله |
\f | شخصیت خط تغذیه |
\u0085 | کاراکتر خط بعدی |
\u2028 | جداکننده خط |
\u2029 | جداکننده پاراگراف |
متاکاراکتر | شرح |
---|---|
[abc] | هر یک از کاراکترهای فهرست شده (a، b یا c) |
[^abc] | هر کاراکتری غیر از موارد ذکر شده (نه a، b یا c) |
[a-zA-Z] | محدوده های ادغام شده (نویسه های لاتین از a تا z، حساس به حروف کوچک و بزرگ) |
[تبلیغ[mp]] | اتحاد کاراکترها (از a به d و از m تا p) |
[az&&[def]] | تقاطع کاراکترها (d، e، f) |
[az&&[^bc]] | تفریق کاراکترها (a, dz) |
متاکاراکتر | شرح |
---|---|
? | یکی یا هیچ کدام |
* | صفر یا چند بار |
+ | یک یا چند بار |
{n} | n بار |
{n،} | n بار یا بیشتر |
{n,m} | حداقل n بار و نه بیشتر از m بار |
کمیت کننده های حریص
چیزی که باید در مورد کمیت کننده ها بدانید این است که آنها در سه نوع مختلف وجود دارند: حریص، تملک و بی میل. شما با افزودن یک+
کاراکتر " " بعد از کمیت، یک کمیت را مالکیت می کنید. با افزودن " " آن را بی میل می کنید ?
. مثلا:
"A.+a" // greedy
"A.++a" // possessive
"A.+?a" // reluctant
بیایید سعی کنیم از این الگو برای درک نحوه عملکرد انواع مختلف کمی سازها استفاده کنیم. به طور پیش فرض، کمیت کننده ها حریص هستند. این بدان معنی است که آنها به دنبال طولانی ترین مسابقه در رشته هستند. اگر کد زیر را اجرا کنیم:
public static void main(String[] args) {
String text = "Fred Anna Alexander";
Pattern pattern = Pattern.compile("A.+a");
Matcher matcher = pattern.matcher(text);
while (matcher.find()) {
System.out.println(text.substring(matcher.start(), matcher.end()));
}
}
این خروجی را می گیریم:
Anna Alexa
برای عبارت منظم " A.+a
"، تطبیق الگو به صورت زیر انجام می شود:
-
اولین کاراکتر در الگوی مشخص شده حرف لاتین است
A
.Matcher
با شروع از شاخص صفر، آن را با هر کاراکتر متن مقایسه می کند. کاراکترF
در متن ما در شاخص صفر است، بنابراینMatcher
از طریق کاراکترها تکرار می شود تا زمانی که با الگو مطابقت داشته باشد. در مثال ما، این کاراکتر در شاخص 5 یافت می شود. -
هنگامی که یک تطابق با کاراکتر اول الگو پیدا شد،
Matcher
به دنبال تطابق با کاراکتر دوم آن میگردد. در مورد ما، این.
کاراکتر " " است که مخفف هر کاراکتری است.شخصیت
n
در جایگاه ششم قرار دارد. مطمئناً به عنوان یک مسابقه برای "هر شخصیت" واجد شرایط است. -
Matcher
به بررسی کاراکتر بعدی الگو ادامه می دهد. در الگوی ما، در کمیتی که برای کاراکتر قبلی اعمال میشود، گنجانده شده است: ".+
". از آنجا که تعداد تکرارهای "هر کاراکتری" در الگوی ما یک یا چند بار است،Matcher
به طور مکرر کاراکتر بعدی را از رشته می گیرد و تا زمانی که با "هر کاراکتری" مطابقت دارد، آن را با الگو بررسی می کند. در مثال ما - تا انتهای رشته (از شاخص 7 تا شاخص 18).اساساً،
Matcher
رشته را تا انتها می بلعد - این دقیقاً همان چیزی است که از "طمع" استفاده می شود. -
پس از اینکه Matcher به انتهای متن رسید و بررسی
A.+
قسمت " " الگو را تمام کرد، شروع به بررسی بقیه الگو می کند:a
. دیگر متنی در آینده وجود ندارد، بنابراین بررسی با «بازگشت» ادامه مییابد و از آخرین کاراکتر شروع میشود: -
Matcher
تعداد تکرارها را در.+
قسمت " " الگوی "به خاطر می آورد". در این مرحله، تعداد تکرارها را یک بار کاهش می دهد و الگوی بزرگتر را در مقابل متن بررسی می کند تا زمانی که مطابقت پیدا شود:
کمیت کننده های مالکیتی
کمیت کننده های مالک بسیار شبیه به حریصان هستند. تفاوت در این است که وقتی متن تا انتهای رشته گرفته می شود، هیچ تطبیق الگو در حین "بازگشت" وجود ندارد. به عبارت دیگر، سه مرحله اول مانند کمی سازهای حریص است. پس از گرفتن کل رشته، تطبیق دهنده بقیه الگو را به آنچه در نظر می گیرد اضافه می کند و آن را با رشته ضبط شده مقایسه می کند. در مثال ما، با استفاده از عبارت منظم "A.++a
"، متد اصلی هیچ مطابقتی پیدا نمی کند. 
کمی سازهای بی میل
-
برای این کمیتکنندهها، مانند انواع حریص، کد به دنبال تطابق بر اساس اولین کاراکتر الگو میگردد:
-
سپس به دنبال مطابقت با کاراکتر بعدی الگو (هر کاراکتری) میگردد:
-
بر خلاف تطبیق الگوی حریصانه، کوتاهترین تطابق در تطابق الگوی بیمیل جستجو میشود. این به این معنی است که پس از یافتن یک تطابق با کاراکتر دوم الگو (یک نقطه، که با کاراکتر در موقعیت 6 متن مطابقت دارد،
Matcher
بررسی میکند که آیا متن با بقیه الگو - کاراکتر " مطابقت دارد یا خیرa
. -
متن با الگو مطابقت ندارد (یعنی دارای کاراکتر "
n
" در نمایه 7 است)، بنابراینMatcher
یک "هر کاراکتر" بیشتری اضافه می کند، زیرا کمیت یک یا چند کاراکتر را نشان می دهد. سپس دوباره الگو را با متن در موقعیت های 5 تا 8 مقایسه می کند:
در مورد ما تطبیق پیدا می شود، اما هنوز به انتهای متن نرسیده ایم. بنابراین، تطبیق الگو از موقعیت 9 مجدداً شروع می شود، یعنی اولین کاراکتر الگو با استفاده از یک الگوریتم مشابه جستجو می شود و این کار تا پایان متن تکرار می شود.

main
روش هنگام استفاده از الگوی " A.+?a
" نتیجه زیر را به دست می آورد: آنا الکسا همانطور که از مثال ما می بینید، انواع مختلف کمیت کننده ها نتایج متفاوتی را برای یک الگو تولید می کنند. پس این را در نظر داشته باشید و بر اساس آنچه به دنبال آن هستید، تنوع مناسب را انتخاب کنید.
فرار از کاراکترها در عبارات منظم
از آنجایی که یک عبارت منظم در جاوا، یا بهتر است بگوییم، نمایش اصلی آن، یک رشته واقعی است، ما باید قوانین جاوا را در مورد حروف رشته ای در نظر بگیریم. به طور خاص، کاراکتر بک اسلش "\
" در رشته های literals در کد منبع جاوا به عنوان یک کاراکتر کنترلی تفسیر می شود که به کامپایلر می گوید که کاراکتر بعدی خاص است و باید به روش خاصی تفسیر شود. مثلا:
String s = "The root directory is \nWindows"; // Move "Windows" to a new line
String s = "The root directory is \u00A7Windows"; // Insert a paragraph symbol before "Windows"
این بدان معنی است که حروف الفبای رشته ای که عبارات منظم را توصیف می کنند و از \
کاراکترهای " " استفاده می کنند (یعنی برای نشان دادن متاکاراکترها) باید اسلش های معکوس را تکرار کنند تا اطمینان حاصل شود که کامپایلر بایت کد جاوا رشته را اشتباه تفسیر نمی کند. مثلا:
String regex = "\\s"; // Pattern for matching a whitespace character
String regex = "\"Windows\""; // Pattern for matching "Windows"
برای فرار از کاراکترهای خاصی که می خواهیم به عنوان کاراکترهای "عادی" از آنها استفاده کنیم، باید از بک اسلش های دوگانه نیز استفاده شود. مثلا:
String regex = "How\\?"; // Pattern for matching "How?"
روش های کلاس الگو
کلاسPattern
متدهای دیگری برای کار با عبارات منظم دارد:
-
String pattern()
‒ نمایش رشته اصلی عبارت منظم را که برای ایجادPattern
شیء استفاده شده است، برمی گرداند:Pattern pattern = Pattern.compile("abc"); System.out.println(pattern.pattern()); // "abc"
-
static boolean matches(String regex, CharSequence input)
- به شما امکان می دهد عبارت منظم ارسال شده به عنوان regex را در مقابل متن ارسال شده به عنوان بررسی کنیدinput
. برمی گرداند:درست - اگر متن با الگو مطابقت داشته باشد.
نادرست - اگر اینطور نیست؛مثلا:
System.out.println(Pattern.matches("A.+a","Anna")); // true System.out.println(Pattern.matches("A.+a","Fred Anna Alexander")); // false
-
int flags()
‒ مقدارflags
مجموعه پارامترهای الگو را هنگام ایجاد الگو یا 0 را اگر پارامتر تنظیم نشده بود، برمیگرداند. مثلا:Pattern pattern = Pattern.compile("abc"); System.out.println(pattern.flags()); // 0 Pattern pattern = Pattern.compile("abc",Pattern.CASE_INSENSITIVE); System.out.println(pattern.flags()); // 2
-
String[] split(CharSequence text, int limit)
- متن ارسال شده را به یکString
آرایه تقسیم می کند. پارامترlimit
حداکثر تعداد منطبقات جستجو شده در متن را نشان می دهد:- اگر
limit > 0
‒limit-1
مطابقت دارد؛ - اگر
limit < 0
‒ همه در متن مطابقت دارند - اگر
limit = 0
‒ همه موارد در متن مطابقت داشته باشد، رشته های خالی در انتهای آرایه کنار گذاشته می شوند.
مثلا:
public static void main(String[] args) { String text = "Fred Anna Alexa"; Pattern pattern = Pattern.compile("\\s"); String[] strings = pattern.split(text,2); for (String s : strings) { System.out.println(s); } System.out.println("---------"); String[] strings1 = pattern.split(text); for (String s : strings1) { System.out.println(s); } }
خروجی کنسول:
Fred Anna Alexa --------- Fred Anna Alexa
در زیر یکی دیگر از متدهای کلاس مورد استفاده برای ایجاد یک
Matcher
شی را در نظر خواهیم گرفت. - اگر
روش های کلاس Matcher
نمونه هایی ازMatcher
کلاس برای انجام تطبیق الگو ایجاد می شوند. Matcher
"موتور جستجو" برای عبارات منظم است. برای انجام یک جستجو، باید دو چیز به آن بدهیم: یک الگو و یک شاخص شروع. برای ایجاد یک Matcher
شی، Pattern
کلاس متد زیر را ارائه می دهد: рublic Matcher matcher(CharSequence input)
متد یک دنباله کاراکتر می گیرد که جستجو می شود. این نمونه ای از کلاسی است که اینترفیس را پیاده سازی می کند CharSequence
. شما می توانید نه تنها یک String
، بلکه یک StringBuffer
،،،، یا را StringBuilder
پاس کنید . الگو شیئی است که متد بر روی آن فراخوانی می شود. نمونه ای از ایجاد تطبیق: Segment
CharBuffer
Pattern
matcher
Pattern p = Pattern.compile("a*b"); // Create a compiled representation of the regular expression
Matcher m = p.matcher("aaaaab"); // Create a "search engine" to search the text "aaaaab" for the pattern "a*b"
اکنون می توانیم از "موتور جستجو" خود برای جستجوی موارد منطبق استفاده کنیم، موقعیت یک مطابقت را در متن بدست آوریم و با استفاده از متدهای کلاس، متن را جایگزین کنیم. این boolean find()
روش به دنبال مطابقت بعدی در متن است. ما می توانیم از این روش و یک دستور حلقه برای تجزیه و تحلیل کل متن به عنوان بخشی از یک مدل رویداد استفاده کنیم. به عبارت دیگر، زمانی که یک رویداد رخ می دهد، یعنی زمانی که یک مطابقت در متن پیدا می کنیم، می توانیم عملیات لازم را انجام دهیم. به عنوان مثال، ما می توانیم از این کلاس int start()
و int end()
متدها برای تعیین موقعیت یک مطابقت در متن استفاده کنیم. و می توانیم از متدهای String replaceFirst(String replacement)
و String replaceAll(String replacement)
برای جایگزینی مطابقت ها با مقدار پارامتر جایگزینی استفاده کنیم. مثلا:
public static void main(String[] args) {
String text = "Fred Anna Alexa";
Pattern pattern = Pattern.compile("A.+?a");
Matcher matcher = pattern.matcher(text);
while (matcher.find()) {
int start=matcher.start();
int end=matcher.end();
System.out.println("Match found: " + text.substring(start, end) + " from index "+ start + " through " + (end-1));
}
System.out.println(matcher.replaceFirst("Ira"));
System.out.println(matcher.replaceAll("Mary"));
System.out.println(text);
}
خروجی:
Match found: Anna from index 5 through 8
Match found: Alexa from index 10 through 14
Fred Ira Alexa
Fred Mary Mary
Fred Anna Alexa
مثال روشن می کند که متدهای replaceFirst
و replaceAll
یک String
شی جدید ایجاد می کنند - رشته ای که در آن الگوهای منطبق در متن اصلی با متن ارسال شده به متد به عنوان آرگومان جایگزین می شوند. علاوه بر این، replaceFirst
متد فقط اولین تطابق را جایگزین میکند، اما replaceAll
روش جایگزین همه موارد مطابق در متن میشود. متن اصلی بدون تغییر باقی مانده است. متداولترین عملیات regex کلاسها مستقیماً در Pattern
کلاس ساخته میشوند . اینها روشهایی مانند , , , و . اما در زیر هود، این روش ها از کلاس های and استفاده می کنند . بنابراین اگر می خواهید بدون نوشتن کد اضافی، متن را جایگزین متن یا مقایسه رشته ها در برنامه کنید، از متدهای کلاس استفاده کنید . اگر به ویژگی های پیشرفته تری نیاز دارید، کلاس ها و را به خاطر بسپارید . Matcher
String
split
matches
replaceFirst
replaceAll
Pattern
Matcher
String
Pattern
Matcher
نتیجه
در یک برنامه جاوا، یک عبارت منظم توسط رشته ای تعریف می شود که از قوانین تطبیق الگوی خاصی پیروی می کند. هنگام اجرای کد، ماشین جاوا این رشته را در یکPattern
شی کامپایل می کند و از یک Matcher
شی برای یافتن مطابقت در متن استفاده می کند. همانطور که در ابتدا گفتم، مردم اغلب عبارات منظم را برای بعد موکول می کنند و آنها را موضوعی دشوار می دانند. اما اگر نحو اولیه، متاکاراکترها و فرار کاراکترها را درک کنید و نمونههایی از عبارات منظم را مطالعه کنید، متوجه خواهید شد که آنها بسیار سادهتر از آن چیزی هستند که در نگاه اول به نظر میرسند.
ادامه مطلب: |
---|
GO TO FULL VERSION