بیان منظم RegEx چیست؟
در واقع یک عبارت منظم (RegEx در جاوا) الگویی برای جستجوی یک رشته در متن است. در جاوا، نمایش اولیه این الگو همیشه یک رشته است، یعنی یک شی از کلاس String. با این حال، هیچ رشته ای را نمی توان در یک عبارت منظم کامپایل کرد، فقط آنهایی که از قوانین نوشتن یک عبارت منظم پیروی می کنند - نحوی که در مشخصات زبان تعریف شده است. برای نوشتن یک عبارت منظم، از کاراکترهای الفبایی و عددی و همچنین متاکاراکترها - کاراکترهایی که معنای خاصی در نحو عبارات منظم دارند، استفاده می شود. مثلا:String regex = "java"; // string template "java";
String regex = "\\d{3}"; // string template of three numeric characters;
ایجاد عبارات منظم در جاوا
برای ایجاد یک RegEx در جاوا، باید دو مرحله ساده را دنبال کنید:- آن را به عنوان یک رشته با استفاده از نحو عبارت منظم بنویسید.
- این رشته را به یک عبارت منظم کامپایل کنید.
Pattern
. برای انجام این کار، باید یکی از دو متد استاتیک موجود در کلاس را فراخوانی کنید 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);//searching for matches with the pattern will be done case-insensitively.
در اصل، کلاس Pattern
یک سازنده عبارت منظم است. در زیر هود، متد compile
سازنده خصوصی کلاس را فراخوانی می کند Pattern
تا یک نمای کامپایل شده ایجاد کند. این روش ایجاد یک نمونه الگو با هدف ایجاد آن به عنوان یک شیء تغییرناپذیر پیاده سازی می شود. هنگام ایجاد، یک بررسی نحوی از عبارت منظم انجام می شود. اگر خطایی در خط وجود داشته باشد، یک استثنا ایجاد می شود PatternSyntaxException
.
نحو عبارت منظم
نحو عبارت منظم مبتنی بر استفاده از نمادها است<([{\^-=$!|]})?*+.>
که می توانند با کاراکترهای الفبایی ترکیب شوند. بسته به نقش آنها می توان آنها را به چند گروه تقسیم کرد:
متاکاراکتر | هدف |
---|---|
^ | شروع خط |
$ | آخر خط |
\b | مرز کلمه |
\ B | نه محدودیت کلمه |
\آ | شروع ورودی |
\G | پایان مسابقه قبلی |
\Z | پایان ورودی |
\z | پایان ورودی |
متاکاراکتر | هدف |
---|---|
\d | نماد دیجیتال |
\ D | کاراکتر غیر عددی |
\s | شخصیت فضایی |
\S | کاراکتر بدون فضای سفید |
\w | کاراکتر الفبایی یا زیرخط |
\ W | هر کاراکتری غیر از حروف الفبا، عددی یا خط زیر |
. | هر شخصیت |
متاکاراکتر | هدف |
---|---|
\ t | کاراکتر برگه |
\n | شخصیت خط جدید |
\r | کاراکتر بازگشت کالسکه |
\f | رفتن به صفحه جدید |
\u0085 | کاراکتر خط بعدی |
\u 2028 | کاراکتر جداکننده خط |
\u 2029 | نماد جداکننده پاراگراف |
متاکاراکتر | هدف |
---|---|
[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 mode
"A.++a" // over-greedy mode
"A.+?a" // lazy mode
با استفاده از این الگو به عنوان مثال، بیایید سعی کنیم بفهمیم که چگونه کمیسازها در حالتهای مختلف کار میکنند. به طور پیش فرض، کمیت در حالت حریص کار می کند. این بدان معنی است که به دنبال طولانی ترین تطابق ممکن در رشته است. در نتیجه اجرای این کد:
public static void main(String[] args) {
String text = "Egor Alla Alexander";
Pattern pattern = Pattern.compile("A.+a");
Matcher matcher = pattern.matcher(text);
while (matcher.find()) {
System.out.println(text.substring(matcher.start(), matcher.end()));
}
}
ما خروجی زیر را دریافت خواهیم کرد: Alla Alexa الگوریتم جستجو برای یک الگوی داده شده " А.+а
" به ترتیب زیر اجرا می شود:
-
در الگوی داده شده، اولین کاراکتر کاراکتر حرف روسی است
А
.Matcher
آن را با هر کاراکتر متن مطابقت می دهد و از موقعیت صفر شروع می شود. در موقعیت صفر در متن ما یک نماد وجود داردЕ
، بنابراینMatcher
به ترتیب از کاراکترهای متن عبور می کند تا زمانی که با الگو مطابقت داشته باشد. در مثال ما، این نماد در موقعیت شماره 5 است. -
پس از یافتن یک تطابق با کاراکتر اول الگو،
Matcher
مطابقت را با کاراکتر دوم الگو بررسی میکند. در مورد ما، این نماد ".
" است که مخفف هر کاراکتری است.در جایگاه ششم نماد حرف قرار دارد
л
. البته با الگوی «هر شخصیتی» مطابقت دارد. -
Matcher
به بررسی کاراکتر بعدی از الگو می رود. در قالب ما، با استفاده از کمیت " " مشخص شده است.+
. از آنجایی که تعداد تکرار "هر کاراکتری" در الگو یک یا چند بار است،Matcher
تا زمانی که شرط "هر کاراکتری" وجود داشته باشد، به نوبه خود نویسه بعدی را از رشته می گیرد و آن را برای مطابقت با الگو بررسی می کند. در مثال ما - تا انتهای خط ( از موقعیت شماره 7 - شماره 18 متن).در واقع،
Matcher
کل خط را تا انتها ضبط می کند - اینجاست که "طمع" آن خود را نشان می دهد. -
پس از
Matcher
رسیدن به انتهای متن و اتمام بررسی قسمت "А.+
" از الگو، Matcher شروع به بررسی بقیه الگو - کاراکتر حرف میکندа
. از آنجایی که متن در جهت جلو به پایان رسیده است، بررسی در جهت معکوس انجام می شود و از آخرین کاراکتر شروع می شود: -
Matcher
تعداد تکرارهای الگوی ".+
" را که به انتهای متن رسیده است، "به خاطر می آورد"، بنابراین تعداد تکرارها را یک بار کاهش می دهد و الگوی متن را بررسی می کند تا زمانی که مطابقت پیدا شود:
حالت کمیت فوق العاده حریص
در حالت فوق العاده حریص، تطبیق مشابه مکانیسم حالت حریص عمل می کند. تفاوت این است که وقتی متن را تا انتهای خط می گیرید، هیچ جستجوی به عقب وجود ندارد. یعنی سه مرحله اول در حالت فوق حریص شبیه حالت حریص خواهد بود. پس از گرفتن کل رشته، تطبیق دهنده بقیه الگو را اضافه می کند و آن را با رشته ضبط شده مقایسه می کند. در مثال ما، هنگام اجرای متد اصلی با الگوی "А.++а
"، هیچ منطبقی پیدا نخواهد شد.
حالت کمیت کننده تنبل
-
در این حالت، در مرحله اولیه، مانند حالت حریص، مطابقت با اولین کاراکتر الگو جستجو می شود:
-
بعد، به دنبال تطابق با کاراکتر بعدی در الگو - هر کاراکتری است:
-
بر خلاف حالت حریص، حالت تنبل کوتاه ترین تطابق را در متن جستجو می کند، بنابراین پس از یافتن تطابق با کاراکتر دوم الگو که با یک نقطه مشخص شده و با کاراکتر در موقعیت شماره 6 متن مطابقت دارد، آن را پیدا می کند.
Matcher
بررسی خواهد کرد که آیا متن با بقیه الگو مطابقت دارد - کاراکتر "а
" . -
از آنجایی که مطابقت با الگوی متن پیدا نشد (در موقعیت شماره 7 در متن علامت " " وجود دارد
л
)،Matcher
"هر کاراکتری" دیگری به الگو اضافه می کند، زیرا به عنوان یک یا چند بار مشخص شده است. و دوباره الگو را با متن در موقعیت های شماره 5 تا 8 مقایسه می کند: -
در مورد ما مطابقت پیدا شد، اما هنوز به انتهای متن نرسیده است. بنابراین، از موقعیت شماره 9، بررسی با جستجوی اولین کاراکتر الگو با استفاده از الگوریتم مشابه آغاز می شود و سپس تا انتهای متن تکرار می شود.
main
هنگام استفاده از А.+?а
الگوی " "، نتیجه زیر را دریافت خواهیم کرد: Alla Alexa همانطور که از مثال ما مشخص است، هنگام استفاده از حالت های مختلف کمیت برای یک الگو، نتایج متفاوتی دریافت کردیم. بنابراین باید این ویژگی را در نظر گرفت و بسته به نتیجه دلخواه در حین جستجو حالت مورد نظر را انتخاب کرد.
فرار از کاراکترها در عبارات منظم
از آنجایی که یک عبارت منظم در جاوا، یا به طور دقیقتر نمایش اولیه آن، با استفاده از یک رشته لفظی مشخص میشود، لازم است قوانین مشخصات جاوا را که مربوط به حروف رشتهای است، در نظر بگیریم. به طور خاص، کاراکتر بک اسلش "\
" در متن های رشته ای در کد منبع جاوا به عنوان یک کاراکتر فرار تعبیر می شود که به کامپایلر هشدار می دهد که کاراکتری که به دنبال آن می آید یک کاراکتر خاص است و باید به روش خاصی تفسیر شود. مثلا:
String s = "The root directory is \nWindows";//wrap Windows to a new line
String s = "The root directory is \u00A7Windows";//insert paragraph character before Windows
بنابراین، در لفظهای رشته ای که یک عبارت منظم را توصیف می کنند و از \
کاراکتر " " استفاده می کنند (مثلاً برای متاکراکترها)، باید آن را دو برابر کرد تا کامپایلر بایت کد جاوا آن را به گونه ای متفاوت تفسیر نکند. مثلا:
String regex = "\\s"; // template for searching for space characters
String regex = "\"Windows\""; // pattern to search for the string "Windows"
اگر قصد داریم از آنها به عنوان کاراکترهای "عادی" استفاده کنیم، باید از کاراکتر بک اسلش دوتایی نیز برای فرار از کاراکترهای خاص استفاده شود. مثلا:
String regex = "How\\?"; // template for searching the string "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
. برمیگرداند: true – اگر متن با الگو مطابقت داشته باشد. نادرست - در غیر این صورت؛ مثال:
System.out.println(Pattern.matches("A.+a","Alla"));//true
System.out.println(Pattern.matches("A.+a","Egor Alla 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
– تمام موارد منطبق در متن را جستجو می کند - When
limit=0
– تمام موارد منطبق را در متن جستجو می کند، در حالی که خطوط خالی در انتهای آرایه حذف می شوند.
public static void main(String[] args) {
String text = "Egor Alla Anna";
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);
}
}
خروجی کنسول: Egor Alla Anna -------- Egor Alla Anna روش کلاس دیگری را برای ایجاد یک شی Matcher
در زیر در نظر خواهیم گرفت.
روش های کلاس مطابقت
Matcher
کلاسی است که از آن یک شی برای جستجوی الگوها ایجاد می شود. Matcher
- این یک "موتور جستجو"، یک "موتور" از عبارات منظم است. برای جستجو، باید دو چیز به او داده شود: یک الگوی جستجو و یک «آدرس» برای جستجو. برای ایجاد یک شی، Matcher
متد زیر در کلاس ارائه می شود Pattern
: рublic Matcher matcher(CharSequence input)
به عنوان آرگومان، متد دنباله ای از کاراکترها را می گیرد که جستجو در آنها انجام می شود. اینها اشیاء کلاسهایی هستند که رابط را پیاده سازی می کنند CharSequence
. String
شما می توانید نه تنها , بلکه StringBuffer
, StringBuilder
و به عنوان استدلال Segment
نیز عبور دهید CharBuffer
. الگوی جستجو شی کلاسی است Pattern
که متد بر روی آن فراخوانی می شود matcher
. نمونه ای از ایجاد تطبیق:
Pattern p = Pattern.compile("a*b");// compiled the regular expression into a view
Matcher m = p.matcher("aaaaab");//created a search engine in the text “aaaaab” using 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 = "Egor Alla Anna";
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) + " с "+ start + " By " + (end-1) + "position");
}
System.out.println(matcher.replaceFirst("Ira"));
System.out.println(matcher.replaceAll("Olga"));
System.out.println(text);
}
خروجی برنامه: یک مسابقه پیدا شد Alla از 5 تا 8 موقعیت یک مطابقت پیدا شد آنا از 10 تا 13 موقعیت Egor Ira Anna Egor Olga Olga Egor Alla Anna از مثال مشخص است که روش ها یک شی جدید replaceFirst
ایجاد می کنند - یک رشته که متن منبعی است که در آن مطابق با الگو با متن ارسال شده به متد به عنوان آرگومان جایگزین می شود. علاوه بر این، روش فقط جایگزین اولین مسابقه و همه موارد در آزمون می شود. متن اصلی بدون تغییر باقی مانده است. استفاده از سایر متدهای کلاس و همچنین نمونههایی از عبارات منظم را میتوانید در این سری مقالات بیابید . رایج ترین عملیات با عبارات منظم هنگام کار با متن از کلاس ها هستند و در داخل آن تعبیه شده اند . اینها روشهایی مانند , , , . اما در واقع «زیر کاپوت» از و . بنابراین، اگر نیاز به جایگزینی متن یا مقایسه رشته ها در یک برنامه بدون نوشتن کد غیر ضروری دارید، از روش های . اگر به قابلیت های پیشرفته نیاز دارید، به کلاس ها و . replaceAll
String
replaceFirst
replaceAll
Matcher
Pattern
Matcher
String
split
matches
replaceFirst
replaceAll
Pattern
Matcher
String
Pattern
Matcher
نتیجه
یک عبارت منظم در یک برنامه جاوا با استفاده از رشته هایی که با الگوی تعریف شده توسط قوانین مطابقت دارد، توصیف می شود. هنگامی که کد اجرا می شود، جاوا این رشته را در یک شی کلاس دوباره کامپایل می کندPattern
و از شی کلاس Matcher
برای یافتن موارد مطابق در متن استفاده می کند. همانطور که در ابتدا گفتم، عبارات منظم اغلب برای بعداً کنار گذاشته می شوند و موضوعی دشوار در نظر گرفته می شود. با این حال، اگر اصول نحو، فراکاراکترها، فرار کردن، و مطالعه نمونههایی از عبارات منظم را بدانید، آنها بسیار سادهتر از آن چیزی هستند که در نگاه اول به نظر میرسند.
GO TO FULL VERSION