ترجمه‌ای از راهنمای کوتاه برای عبارات منظم در جاوا را که توسط جف فریسن برای وب‌سایت javaworld نوشته شده است، به اطلاع شما می‌رسانیم . برای سهولت در مطالعه مقاله را به چند قسمت تقسیم کرده ایم. عبارات منظم در جاوا، قسمت 2 - 1عبارات منظم در جاوا، قسمت 1
ادغام چندین محدوده
با قرار دادن آنها در کنار هم می توانید چندین محدوده را در یک کلاس کاراکتر محدوده واحد ادغام کنید. به عنوان مثال، کلاس [a-zA-Z]تمام حروف الفبای لاتین را با حروف کوچک یا بزرگ مطابقت می دهد.

ادغام چندین محدوده

با قرار دادن آنها در کنار هم می توانید چندین محدوده را در یک کلاس کاراکتر محدوده واحد ادغام کنید. به عنوان مثال، کلاس [a-zA-Z]تمام حروف الفبای لاتین را با حروف کوچک یا بزرگ مطابقت می دهد.

ترکیب کلاس های شخصیت

یک اتحادیه کلاس کاراکتر از چندین کلاس کاراکتر تودرتو تشکیل شده است و با تمام کاراکترهای اتحاد حاصل مطابقت دارد. به عنوان مثال، کلاس [a-d[m-p]]کاراکترهای از aبه dو از mبه را مطابقت می دهد p. مثال زیر را در نظر بگیرید: java RegexDemo [ab[c-e]] abcdef این مثال کاراکترهای a, b, و , cرا که برای آنها مطابقت دارد در : deabcdef
regex = [ab[c-e]]
input = abcdef
Found [a] starting at 0 and ending at 0
Found [b] starting at 1 and ending at 1
Found [c] starting at 2 and ending at 2
Found [d] starting at 3 and ending at 3
Found [e] starting at 4 and ending at 4

تقاطع کلاس کاراکتر

تقاطع کلاس های کاراکتر از کاراکترهای مشترک برای همه کلاس های تودرتو تشکیل شده است و فقط با کاراکترهای مشترک مطابقت دارد. به عنوان مثال، کلاس با [a-z&&[d-f]]کاراکترها مطابقت دارد و . مثال زیر را در نظر بگیرید: توجه داشته باشید که در سیستم عامل ویندوز من، دو نقل قول مورد نیاز است زیرا پوسته فرمان آنها را به عنوان یک جداکننده دستور در نظر می گیرد. این مثال فقط شخصیتی را پیدا می کند که در : defjava RegexDemo "[aeiouy&&[y]]" party&yparty
regex = [aeiouy&&[y]]
input = party
Found [y] starting at 4 and ending at 4

کم کردن کلاس های کاراکتر

کلاس‌های کاراکتر تفریق شامل همه نویسه‌ها به جز آنهایی است که در کلاس‌های کاراکتر تودرتو قرار دارند، و فقط با کاراکترهای باقی‌مانده مطابقت دارد. به عنوان مثال، کلاس [a-z&&[^m-p]]کاراکترهای از aبه lو از qبه را مطابقت می‌دهد z: java RegexDemo "[a-f&&[^a-c]&&[^e]]" abcdefg این مثال کاراکترهایی dرا پیدا می‌کند fکه برای آنها مطابقت دارد abcdefg:
regex = [a-f&&[^a-c]&&[^e]]
input = abcdefg
Found [d] starting at 3 and ending at 3
Found [f] starting at 5 and ending at 5

کلاس های کاراکتر از پیش تعریف شده

برخی از کلاس های کاراکتر به اندازه کافی در عبارات منظم ظاهر می شوند تا استفاده از علامت کوتاه را توجیه کنند. کلاس Patternکلاس های کاراکتر از پیش تعریف شده را به عنوان اختصارات ارائه می دهد. می‌توانید از آنها برای ساده‌سازی عبارات منظم و به حداقل رساندن خطاهای نحوی استفاده کنید. چندین دسته از کلاس های کاراکتر از پیش تعریف شده وجود دارد: java.lang.Characterویژگی های استاندارد، POSIX و Unicode مانند اسکریپت، بلوک، دسته بندی و باینری. لیست زیر فقط دسته کلاس های استاندارد را نشان می دهد:
  • \d: عدد. معادل [0-9].
  • \D: کاراکتر غیر عددی. معادل [^0-9].
  • \s: کاراکتر فضای خالی. معادل [ \t\n\x0B\f\r].
  • \S: یک کاراکتر فضای خالی نیست. معادل [^\s].
  • \w: نماد واژه ساز. معادل [a-zA-Z_0-9].
  • \W: شخصیت کلمه ساز نیست. معادل [^\w].
مثال زیر از یک کلاس کاراکتر از پیش تعریف شده \wبرای توصیف همه کاراکترهای کلمه در متن ورودی استفاده می کند: java RegexDemo \w "aZ.8 _" به نتایج اجرای زیر دقت کنید، که نشان می دهد کاراکترهای نقطه و فاصله کاراکتر کلمه در نظر گرفته نمی شوند:
regex = \w
input = aZ.8 _
Found [a] starting at 0 and ending at 0
Found [Z] starting at 1 and ending at 1
Found [8] starting at 3 and ending at 3
Found [_] starting at 5 and ending at 5
جداکننده های خطوط
مستندات کلاس SDK، Patternمتاکاراکتر نقطه‌ای را به عنوان یک کلاس کاراکتر از پیش تعریف‌شده توصیف می‌کند که با هر کاراکتری به‌جز جداکننده‌های خط (توالی‌های یک یا دو نویسه‌ای که انتهای یک خط را مشخص می‌کنند) مطابقت دارد. استثنا حالت dotall است (که در ادامه به آن خواهیم پرداخت)، که در آن نقاط نیز با جداکننده خطوط مطابقت دارند. کلاس Patternجداکننده های خط زیر را متمایز می کند:
  • کاراکتر بازگشت کالسکه ( \r);
  • کاراکتر خط جدید (نماد برای پیشبرد کاغذ یک خط) ( \n);
  • یک کاراکتر بازگشتی کالسکه بلافاصله پس از آن یک کاراکتر خط جدید ( \r\n);
  • کاراکتر خط بعدی ( \u0085);
  • کاراکتر جداکننده خط ( \u2028);
  • نماد جداکننده پاراگراف ( \u2029)

گروه های اسیر شده

گروه ضبط برای ذخیره مجموعه کاراکترهای یافت شده برای استفاده بیشتر هنگام جستجو بر اساس الگو استفاده می شود. این ساختار دنباله ای از کاراکترها است که در متاکاراکترها با پرانتز ( ( )) محصور شده اند. هنگام جستجو بر اساس الگو، همه کاراکترهای درون گروه گرفته شده به عنوان یک کل واحد در نظر گرفته می شوند. به عنوان مثال، گروه ضبط ( Java) حروف J، aو vرا aدر یک واحد ترکیب می کند. این گروه ضبط، همه موارد رخداد الگو را Javaدر متن ورودی پیدا می کند. با هر مسابقه، کاراکترهای ذخیره شده قبلی Javaبا شخصیت های بعدی جایگزین می شوند. گروه‌های گرفته شده را می‌توان در گروه‌های دیگر دستگیر شده تودرتو کرد. به عنوان مثال، در یک عبارت منظم، (Java( language))یک گروه (language)در داخل یک گروه تودرتو شده است (Java). به هر گروه ضبط تودرتو یا غیر تودرتو، شماره ای اختصاص داده می شود که از 1 شروع می شود و شماره گذاری از چپ به راست انجام می شود. در مثال قبلی، (Java( language))کبریت‌ها گروه شماره 1 را می‌گیرند و (language)کبریت‌ها گروه شماره 2 را می‌گیرند. در عبارت منظم (a)(b)، (a)کبریت‌ها گروه شماره 1 را می‌گیرند و (b)گروه شماره 2 را ضبط می‌کنند عبارات منظم در جاوا، قسمت 2 - 2. مسابقات ذخیره شده توسط گروه‌های ضبط را می‌توان بعداً با استفاده از ارجاع‌های برگشتی مشاهده کرد. به عنوان یک کاراکتر بک اسلش و به دنبال آن یک کاراکتر عددی مربوط به تعداد گروهی که گرفته شده است، به شما امکان می دهد به کاراکترهای متن گرفته شده توسط گروه اشاره کنید. داشتن یک بک لینک باعث می شود که تطبیق دهنده به نتیجه جستجوی ذخیره شده گروه گرفته شده بر اساس شماره آن مراجعه کند و سپس از کاراکترهای آن نتیجه برای جستجوی بیشتر استفاده کند. مثال زیر استفاده از یک مرجع بازگشتی برای یافتن خطاهای گرامری در متن را نشان می دهد: java RegexDemo "(Java( language)\2)" "The Java language language" این مثال (Java( language)\2)از یک عبارت منظم برای یافتن یک خطای گرامری با کلمه تکراری languageبلافاصله Javaدر متن ورودی استفاده می کند "The Java language language". این عبارت منظم دو گروه را برای گرفتن مشخص می کند: شماره 1 – (Java( language)\2)مربوط به Java language languageو شماره 2 – (language)مربوط به کاراکتر فاصله و به دنبال آن language. مرجع برگشتی \2اجازه می دهد تا نتیجه ذخیره شده گروه شماره 2 دوباره مورد بازبینی قرار گیرد تا تطبیق دهنده بتواند دومین رخداد یک فاصله و به دنبال آن را languageبلافاصله پس از اولین وقوع یک فاصله جستجو کند language. نتایج این دیدار RegexDemoبه شرح زیر است:
regex = (Java( language)\2)
input = The Java language language
Found [Java language language] starting at 4 and ending at 25

تطبیق کننده های مرزی

گاهی اوقات شما نیاز دارید که یک تطبیق الگو در ابتدای یک خط، در مرزهای کلمه، در انتهای متن و غیره انجام دهید. می‌توانید این کار را با استفاده از یکی از تطبیق‌دهنده‌های لبه کلاس Pattern، که ساختارهای عباراتی منظم هستند که در مکان‌های زیر جستجو می‌کنند، انجام دهید:
  • ^: شروع خط;
  • $: آخر خط؛
  • \b: مرز کلمه;
  • \B: مرز شبه واژه;
  • \A: شروع متن;
  • \G: پایان مسابقه قبلی;
  • \Z: انتهای متن، به استثنای جداکننده خطوط انتهایی (در صورت وجود)؛
  • \z: انتهای متن
مثال زیر از ^متاکاراکتر تطبیق کننده مرزی برای یافتن خطوطی استفاده می کند که با Theنویسه های صفر یا چند کلمه ای به دنبال آن شروع می شوند: java RegexDemo "^The\w*" Therefore کاراکتر ^مشخص می کند که سه کاراکتر اول متن ورودی باید با کاراکترهای الگوی متوالی مطابقت داشته باشند T، hو eکه می تواند با هر عددی دنبال شود. نمادهای کلمه ساز اینم نتیجه اجرا:
regex = ^The\w*
input = Therefore
Found [Therefore] starting at 0 and ending at 8
اگر خط فرمان را به تغییر دهید چه اتفاقی می افتد java RegexDemo "^The\w*" " Therefore"؟ هیچ منطبقی پیدا نخواهد شد زیرا Thereforeقبل از متن ورودی یک کاراکتر فاصله وجود دارد.

طول صفر مطابقت دارد

گاهی اوقات هنگام کار با تطبیق‌کننده‌های لبه، با تطبیق‌هایی با طول صفر مواجه می‌شوید. Совпадение нулевой длиныمسابقه ای است که شامل هیچ کاراکتری نمی شود. آنها می توانند در متن ورودی خالی، در ابتدای متن ورودی، بعد از آخرین نویسه متن ورودی، و بین هر دو کاراکتر متن ورودی رخ دهند. مسابقات با طول صفر به راحتی قابل تشخیص هستند زیرا همیشه در یک موقعیت شروع و پایان می یابند. مثال زیر را در نظر بگیرید: java RegExDemo \b\b "Java is" این مثال دو مرز کلمه متوالی را جستجو می کند و نتایج به صورت زیر است:
regex = \b\b
input = Java is
Found [] starting at 0 and ending at -1
Found [] starting at 4 and ending at 3
Found [] starting at 5 and ending at 4
Found [] starting at 7 and ending at 6
ما شاهد چندین مسابقه صفر در نتایج هستیم. موقعیت‌های پایانی در اینجا یک کمتر از موقعیت‌های شروع هستند، زیرا RegexDemoمن در کد منبع در فهرست 1 مشخص کردم end() – 1. عبارات منظم در جاوا، قسمت 2 - 3

کمیت کننده ها

کمیت ساز یک ساختار عبارت منظم است که به طور صریح یا ضمنی یک الگو را با یک مقدار عددی مرتبط می کند. این مقدار عددی تعیین می کند که چند بار الگو را جستجو کنیم. کمیت کننده ها به حریص، تنبل و فوق طمع تقسیم می شوند:
  • کمیت حریص ( ?یا *) +برای یافتن طولانی ترین تطابق طراحی شده است. میتونم بپرسم X؟ برای یافتن یک یا کمتر رخداد X، X*برای یافتن صفر یا چند رخداد X، X+برای یافتن یک یا چند رخداد X، X{n}برای یافتن nرخدادها X، X{n,}یافتن حداقل (و احتمالاً بیشتر) nرخدادها ، Xو X{n,m}یافتن حداقل nاما نه بیشتر mرخدادها X.
  • کمیت تنبل ( ??یا *?) +?برای یافتن کوتاهترین تطابق طراحی شده است. شما می توانید تعیین کنید X??که یک یا کمتر از موارد X، X*? برای یافتن صفر یا چند رخداد X، X+?برای یافتن یک یا چند رخداد X، X{n}?یافتن nرخدادها X، X{n,}?یافتن حداقل (و احتمالاً بیشتر) nرخدادها X، و X{n,m}?یافتن حداقل nاما نه بیشتر از mرخدادها X.
  • کمیت فوق حریص ( ?+یا *+) ++شبیه کمیتگر حریص است، با این تفاوت که کمیت کننده فوق حریص فقط یک بار تلاش می کند تا طولانی ترین تطابق را پیدا کند، در حالی که کمیت کننده حریص می تواند چندین بار تلاش کند. می توان آن را X?+برای یافتن یک یا کمتر رخداد X، X*+برای یافتن صفر یا چند رخداد X، X++برای یافتن یک یا چند رخداد X، X{n}+برای یافتن nرخدادهای X، X{n,}+برای یافتن حداقل (و احتمالاً بیشتر) nرخدادها ، Xو X{n,m}+ یافتن حداقل n، اما نه بیشتر از mوقوع، تنظیم کرد. X.
مثال زیر استفاده از کمیتگر حریص را نشان می دهد: java RegexDemo .*ox "fox box pox" در اینجا نتایج آمده است:
regex = .*ox
input = fox box pox
Found [fox box pox] starting at 0 and ending at 10
کمیت حریص ( .*) طولانی ترین دنباله کاراکترها را پیدا می کند که به ox. کل متن ورودی را مصرف می کند و سپس به عقب برمی گردد تا متوجه شود که متن ورودی با این کاراکترها به پایان می رسد. اکنون کمیت کننده تنبل را در نظر بگیرید: java RegexDemo .*?ox "fox box pox" نتایج آن:
regex = .*?ox
input = fox box pox
Found [fox] starting at 0 and ending at 2
Found [ box] starting at 3 and ending at 6
Found [ pox] starting at 7 and ending at 10
کمیت کننده تنبل ( .*?) کوتاه ترین دنباله کاراکترها را پیدا می کند که به ox. با یک رشته خالی شروع می شود و به تدریج کاراکترها را مصرف می کند تا زمانی که مطابقت پیدا کند. و سپس به کار ادامه می دهد تا متن ورودی تمام شود. در نهایت، بیایید به کمیت فوق العاده حریص نگاه کنیم: java RegexDemo .*+ox "fox box pox" و در اینجا نتایج آن است:
regex = .*+ox
input = fox box pox
کمیت فوق العاده حریص ( .*+) منطبق را پیدا نمی کند زیرا تمام متن ورودی را مصرف می کند و چیزی برای مطابقت oxدر انتهای عبارت منظم باقی نمانده است. بر خلاف کمیت حریص، کمیت کننده فوق حریص به عقب برنمی گردد.

طول صفر مطابقت دارد

گاهی اوقات هنگام کار با کمیت کننده ها با منطبقات با طول صفر مواجه می شوید. به عنوان مثال، استفاده از کمیت‌گر حریص زیر منجر به تطابق چندگانه صفر می‌شود: java RegexDemo a? abaa نتایج اجرای این مثال:
regex = a?
input = abaa
Found [a] starting at 0 and ending at 0
Found [] starting at 1 and ending at 0
Found [a] starting at 2 and ending at 2
Found [a] starting at 3 and ending at 3
Found [] starting at 4 and ending at 3
پنج مسابقه در نتایج اجرا وجود دارد. اگرچه اولین، سوم و چهارم کاملاً مورد انتظار هستند (آنها با موقعیت های سه حرف aدر مطابقت دارند abaa)، دوم و پنجم ممکن است شما را شگفت زده کنند. به نظر می رسد که آنها نشان می دهند که چه چیزی با انتهای متن aمطابقت دارد ، اما در واقعیت اینطور نیست. bعبارت منظم در انتهای متن a?جستجو نمی کند . bحضور یا عدم حضور را جستجو می کند a. هنگامی که a?آن را پیدا نمی کند a، آن را به عنوان یک مطابقت با طول صفر گزارش می دهد.

عبارات پرچم تو در تو

تطبیق‌کنندگان برخی از فرضیات پیش‌فرض را ایجاد می‌کنند که هنگام کامپایل عبارت منظم در یک الگو، می‌توان آنها را نادیده گرفت. در ادامه به این موضوع خواهیم پرداخت. یک عبارت منظم به شما امکان می دهد با استفاده از یک عبارت پرچم تو در تو، هر یک از پیش فرض ها را لغو کنید. این ساختار عبارت منظم به عنوان یک فراکاراکتر از پرانتز در اطراف یک متاکاراکتر علامت سوال ( ?) و به دنبال آن یک حرف لاتین کوچک مشخص می شود. کلاس Patternعبارات پرچم تودرتو زیر را درک می کند:
  • (?i): تطبیق الگوی حساس به حروف بزرگ را فعال می کند. به عنوان مثال، هنگام استفاده از یک دستور، java RegexDemo (?i)tree Treehouseدنباله کاراکترها Treeبا الگو مطابقت دارد tree. پیش فرض جستجوی الگوی حساس به حروف بزرگ و کوچک است.
  • (?x): استفاده از نویسه‌های فضای خالی و کامنت‌هایی که با متاکاراکتر درون الگو شروع می‌شوند را امکان‌پذیر می‌کند #. همسان هر دو را نادیده می گیرد. به عنوان مثال، برای java RegexDemo ".at(?x)#match hat, cat, and so on" matterدنباله ای از کاراکترها matبا الگوی مطابقت دارد .at. به‌طور پیش‌فرض، کاراکترها و کامنت‌های فضای خالی مجاز نیستند و تطبیق‌دهنده آن‌ها را به‌عنوان کاراکترهایی درگیر در جستجو در نظر می‌گیرد.
  • (?s): حالت dotall را فعال می کند، که در آن متاکاراکتر نقطه، جداکننده خطوط را علاوه بر هر کاراکتر دیگری مطابقت می دهد. به عنوان مثال، دستور java RegexDemo (?s). \nیک کاراکتر خط جدید را پیدا می کند. پیش‌فرض برعکس dotall است: هیچ جداکننده خط پیدا نمی‌شود. به عنوان مثال، دستور Java RegexDemo . \nکاراکتر خط جدید را پیدا نمی کند.
  • (?m): حالت چند خطی را فعال می کند، جایی که ^ابتدا و $انتهای هر خط مطابقت دارد. به عنوان مثال، java RegexDemo "(?m)^abc$" abc\nabcهر دو دنباله را در متن ورودی پیدا می کند abc. به طور پیش فرض، حالت تک خطی استفاده می شود: با ^ابتدای کل متن ورودی مطابقت دارد و با $انتهای آن مطابقت دارد. برای مثال، java RegexDemo "^abc$" abc\nabcپاسخی را برمی‌گرداند که هیچ منطبقی وجود ندارد.
  • (?u): تراز حروف حساس به یونیکد را فعال می کند. این پرچم، هنگامی که همراه با استفاده می‌شود (?i)، امکان تطبیق الگوی حساس به حروف بزرگ را مطابق با استاندارد یونیکد فراهم می‌کند. تنظیمات پیش‌فرض این است که فقط نویسه‌های حساس به حروف بزرگ و US-ASCII را جستجو کنید.
  • (?d): حالت رشته به سبک یونیکس را فعال می کند، که در آن تطبیق دهنده متاکاراکترها را در متن .و ^فقط $جداکننده خطوط را تشخیص می دهد \n. حالت پیش‌فرض رشته‌ای به سبک غیر یونیکس است: تطبیق‌دهنده، در زمینه متاکاراکترهای بالا، تمام جداکننده‌های خط را تشخیص می‌دهد.
عبارات پرچم تو در تو شبیه گروه‌های گرفته شده است، زیرا شخصیت‌های آن‌ها توسط فراکاراکترهای پرانتز احاطه شده‌اند. برخلاف گروه‌های ضبط‌شده، عبارات پرچم تودرتو نمونه‌ای از گروه‌های غیر گرفته‌شده هستند، که یک ساختار عبارت منظم هستند که کاراکترهای متنی را نمی‌گیرند. آنها به عنوان دنباله ای از کاراکترها تعریف می شوند که با فراکاراکترهای پرانتز احاطه شده اند.
تعیین چند عبارت پرچم تو در تو
می توان چند عبارت پرچم تو در تو را در یک عبارت منظم با قرار دادن آنها در کنار هم ( (?m)(?i))) یا قرار دادن حروفی که آنها را به صورت متوالی تعریف می کنند ( (?mi)) مشخص کرد.

نتیجه

همانطور که احتمالاً تا به حال متوجه شده اید، عبارات منظم بسیار مفید هستند و با تسلط بر ظرایف نحو آنها بسیار مفیدتر می شوند. تا اینجا شما را با اصول عبارات منظم و Pattern. در قسمت 2، نگاه عمیق‌تری به Regex API خواهیم داشت و روش‌های Pattern, Matcherو را بررسی می‌کنیم PatternSyntaxException. همچنین دو برنامه کاربردی Regex API را به شما نشان خواهم داد که می توانید بلافاصله در برنامه های خود از آنها استفاده کنید. عبارات با قاعده در جاوا، قسمت 3 عبارات با قاعده در جاوا، قسمت 4 عبارات با قاعده در جاوا، قسمت 5