Regex ، کوتاه برای بیان منظم ، اغلب در زبان های برنامه نویسی برای تطبیق الگوهای در رشته ها ، یافتن و جایگزین کردن ، اعتبار ورودی و تغییر متن متن استفاده می شود. یادگیری چگونگی استفاده صحیح از Regex می تواند کار با متن را بسیار ساده تر کند.

Regex syntax، توضیح

Regex به داشتن یک نحو وحشتناک شهرت دارد ، اما نوشتن آن بسیار آسان تر از خواندن است. به عنوان مثال ، در اینجا یک regex عمومی برای اعتبار سنج ایمیل سازگار با RFC 5322 وجود دارد:

 (؟: [a-z0-9!#$%&'*+/=?^_`{|}~-] + (؟: . [a-z0-9!#$%&'*+/=?^_`{|}~-] +) * | "(": [x01-
x08x0bx0cx0e-x1fx21x23-x5bx5d-x7f] | \ [x01-x09x0bx0cx0e-x7f]) * ")
@ (؟: ((:: [a-z0-9]] (؟: [a-z0-9-] * [a-z0-9])؟ .) + [a-z0-9] (؟: [a-z0-9-] * [a-z0-9])؟ |  [(?
:(?:25[0-5] | 2 [19659005] | [01]؟ [0-9][0-9]؟) .) {3} (؟: 25 [0-5] | 2 [0-4][0-9] | [01]؟ [0-
9][0-9]؟ | | [a-z0-9-] * [a-z0-9] :( ؟: [x01-x08x0bx0cx0e-x1fx21-x5ax53-x7f] |
\ [x01-x09x0bx0cx0e-x7f]) +) ]) 

اگر به نظر می رسد کسی چهره خود را به صفحه کلید زده ، شما تنها نیستید. اما در زیر کاپوت ، همه این ظروف سرباز یا مسافر در واقع در حال برنامه نویسی یک دستگاه حالت محدود است. این دستگاه برای هر کاراکتر اجرا می شود ، بر اساس قوانینی که تعیین کرده اید ، به هم پیوسته و مطابقت دارند. بسیاری از ابزارهای آنلاین نمودارهای راه آهن را ارائه می دهند ، و نشان می دهد که دستگاه Regex چگونه کار می کند. در اینجا همان Regex به شکل بصری وجود دارد:

هنوز هم بسیار گیج کننده است ، اما بسیار قابل فهم تر است. این دستگاه با قطعات متحرک است که قوانینی را برای تعیین چگونگی هماهنگی آن تعریف می کند. می توانید ببینید که چگونه کسی این کار را کرده است. این فقط متن بزرگی نیست.

اول از همه: از Debugger Regex استفاده کنید

قبل از شروع کار ، مگر اینکه Regex شما به خصوص کوتاه باشد یا به خصوص مهارت داشته باشید ، باید از یک آنلاین استفاده کنید. اشکال زدایی هنگام نوشتن و آزمایش آن. این درک نحو را بسیار ساده تر می کند. ما Regex101 و RegExr را توصیه می کنیم ، هر دو ارائه دهنده تست و مرجع ساخته شده داخلی هستند.

How Regex چگونه کار می کند؟ این یک نمودار از Regulex است که Regex مطابق با ایمیل بسیار کوتاه (و قطعاً مطابق با RFC 5322) نیست:

موتور Regex در سمت چپ شروع می شود و خطوط را به پایین حرکت می کند ، و با کاراکتر مطابقت دارد. گروه شماره 1 با هر کاراکتر به جز شکستن خط مطابقت دارد و تا زمانی که بلوک بعدی یک مسابقه پیدا کند ، به کاراکترها ادامه می دهد. در این حالت ، هنگامی که به نماد @ می رسد ، متوقف می شود ، به این معنی که گروه شماره 1 آدرس آدرس ایمیل را ضبط می کند و همه چیز پس از منطبق شدن با دامنه.

Regex که گروه شماره 1 را در ما تعریف می کند. مثال ایمیل: [

 (. +) 

پرانتز ها یک گروه ضبط را تعریف می کنند ، که به موتور Regex می گوید مطالب مربوط به این گروه را در یک متغیر ویژه قرار دهد. هنگامی که Regex را روی یک رشته اجرا می کنید ، بازده پیش فرض کل بازی (در این حالت ، کل ایمیل) است. اما این همچنین هر گروه ضبط را برمی گرداند ، که این Regex را برای بیرون کشیدن نام ها از ایمیل مفید می کند.

دوره نماد "هر شخصیتی به جز Newline" است. این همه چیز را به صورت یک خط مطابقت می دهد ، بنابراین اگر این ایمیل را به Regex منتقل کنید آدرس مانند:

٪ $ # ^ &٪ * #٪ $ # ^ @ gmail.com 

مطابقت دارد ٪ $ # ^ &٪ * #٪ $ # ^ به عنوان نام ، گرچه اسرارآمیز است.

نماد (+) یک ساختار کنترلی است که به معنی "یک یا چند بار با شخصیت قبلی یا گروه مطابقت دارد." این تضمین می کند که کل نام مطابقت دارد ، و نه تنها شخصیت اول. این چیزی است که حلقه موجود در نمودار راه آهن را ایجاد می کند.

بقیه Regex برای رمزگشایی نسبتاً ساده است:

 (. +) @ (. +  .. +) 

گروه اول متوقف می شود این نماد @ بازدید می کند. سپس گروه بعدی شروع می شود که مجدداً با کاراکترهای مختلف مطابقت دارد تا اینکه به یک شخصیت دوره ای برسد. به طور صحیح آنها را با یک backslash فرار کنید. در این مثال ، برای مطابقت با دوره ای که می نویسیم . و تجزیه كننده آن را به عنوان یك نمادی كه به معنای "مطابقت با دوره" است ، رفتار می كند.

مطابق شخصیت

اگر در Regex شخصیت های غیر كنترلی داشته باشید ، موتور Regex فرض خواهد كرد كه این شخصیت ها بلوک تطبیقی ​​را تشکیل می دهند. به عنوان مثال ، Regex:

 او + llo 

کلمه "سلام" را با هر تعدادی از موارد دیگر مطابقت خواهد داد.

Regex همچنین کلاس های شخصیت دارد که برای مجموعه ای از کاراکترها به عنوان کوتاه کار می کند. اینها براساس اجرای Regex متفاوت هستند ، اما این تعداد کمی استاندارد هستند:

  • . – با هر چیزی به جز خط جدید مطابقت دارد.
  • w – با هر شخصیت "کلمه" از جمله رقم ها و زیرنویس ها مطابقت دارد.
  • d – شماره های مسابقات.
  • b

این سه دارای همتای بزرگ هستند که عملکرد آنها را معکوس می کند. به عنوان مثال ، D با هر چیزی که عددی نیست ، مطابقت دارد.

Regex همچنین تطبیق کاراکتر را تنظیم می کند. به عنوان مثال:

 [abc] 

یا a ، b یا c مطابقت خواهد داشت. این به عنوان یک بلوک عمل می کند ، و براکت های مربعی فقط ساختارهای کنترل هستند. از طرف دیگر ، می توانید طیف وسیعی از کاراکترها را مشخص کنید:

 [a-c] 

یا مجموعه را نفی کنید ، که مطابق با هر کاراکتر موجود در مجموعه نیست:

 [^a-c] 

Quantifiers

Quantifiers بخش مهمی از Regex است. آنها به شما اجازه می دهند رشته هایی را که قالب دقیق را نمی شناسید ، مطابقت دهید ، اما شما یک ایده بسیار خوب دارید.

اپراتور + از مثال ایمیل یک سنجش دهنده است ، به طور خاص تعیین کننده "یک یا چند" اگر نمی دانیم یک رشته خاص چه مدت است ، اما می دانیم که از شخصیت های الفبایی تشکیل شده است (و خالی نیست) ، می توانیم بنویسیم:

  w + 

علاوه بر + ، همچنین وجود دارد:

  • اپراتور * ، که با "صفر یا بیشتر" مطابقت دارد. در اصل همان + ، به جز این گزینه برای یافتن کبریت نیست.
  • اپراتور ؟ ، که با "صفر یا یک" مطابقت دارد. این اثر باعث می شود که یک شخصیت به صورت اختیاری انتخاب شود. یا در آنجا باشد یا وجود ندارد ، و بیش از یک بار مطابقت نخواهد داشت.
  • تعیین کننده های عددی. اینها می توانند یک عدد واحد مانند 3} باشند ، که به معنی "دقیقاً 3 بار" است ، یا دامنه ای مانند 3-6} . می توانید شماره دوم را برای نامحدود بودن آن بگذارید. به عنوان مثال ، {3 ،} به معنی "3 ​​بار یا بیشتر" است. به اندازه کافی عجیب ، شما نمی توانید شماره اول را کنار بگذارید ، بنابراین اگر می خواهید "3 بار یا کمتر" ، باید

Quantifiers حریص و تنبل

را در زیر کاپوت ، * و + اپراتور حریص هستند . تا آنجا که ممکن است مطابقت داشته باشد و آنچه را که برای شروع بلوک بعدی لازم است را پس می دهد. این می تواند یک مشکل عظیم باشد.

در اینجا مثالی وجود دارد: بگویید که شما می خواهید HTML یا هر چیز دیگری را با بستن بندها مطابقت دهید. متن ورودی شما این است:

 
سلام جهانیان

و شما می خواهید همه چیز را درون براکت ها مطابقت دهید. ممکن است شما چیزی بنویسید: [

 <.*> 

این ایده درستی است ، اما به یک دلیل اساسی شکست نمی خورد: موتور Regex با " div> سلام جهان

" برای دنباله [19459012»مطابقتدارد]. * ، و سپس به عقب برگشت تا مرحله بعدی بازی ، در این حالت یک براکت بسته (> ). انتظار دارید که فقط با " div " مطابقت داشته باشد ، و دوباره تکرار کنید تا با بخش بسته بازی مطابقت داشته باشید. اما backtracker از انتهای رشته کار می کند ، و روی براکت انتهایی متوقف می شود ، که در پایان با همه چیز در داخل براکت ها مطابقت دارد.

راه حل این است که سنجشگر ما را تنبل کنیم ، این بدان معنی است که ممکن است تا حد ممکن با کاراکترهای کمی مطابقت داشته باشد. . در زیر کاپوت ، این در واقع فقط با یک شخصیت مطابقت خواهد داشت ، و سپس برای پر کردن فضا تا مسابقه بلوک بعدی گسترش می یابد ، که این امر باعث می شود عملکرد بسیار بیشتری در عملیات بزرگ Regex انجام شود.

ساختن یک تنبل اندازه گیری با اضافه کردن یک علامت سؤال انجام می شود. مستقیماً بعد از سنج این کمی گیج کننده است زیرا ؟ در حال حاضر یک تعیین کننده است (و در واقع به طور پیش فرض حریص است). برای مثال HTML ما ، Regex با این افزونه ساده ثابت شده است:

 <.*?> 

اپراتور تنبلی را می توان به هر اندازه گیری از جمله ، {0 ، 3}؟ ، و حتی ؟ [. گرچه آخرین اثر آن را ندارد؛ زیرا به هر حال شما با صفر یا یک کاراکتر مطابقت دارید ، جایی برای گسترش وجود ندارد.

گروه بندی و Lookarounds

گروه های Regex اهداف زیادی دارند. در یک سطح پایه ، آنها چندین علائم را در یک بلوک جمع می کنند. به عنوان مثال ، می توانید یک گروه ایجاد کنید ، سپس از کل سنجش در کل گروه استفاده کنید:

 ba (na) + 

این گروه "na" را تکرار می کند تا با عبارت موز ، و banananana ، و غیره. بدون گروه ، موتور Regex فقط با شخصیت خاتمه یافته بارها و بارها مطابقت دارد.

این نوع گروه با دو پرانتز ساده به عنوان گروه ضبط نامیده می شود و آن را در خروجی شامل می کند:

[19659016] اگر می خواهید از این امر جلوگیری کنید ، و به سادگی به دلایل اعدام نشانه گذاری را در کنار یکدیگر قرار دهید ، می توانید از یک گروه غیر ضبط استفاده کنید:

 ba (؟ na) 

علامت سؤال (شخصیت محفوظ) تعریف گروه غیر استاندارد ، و شخصیت زیر مشخص می کند که چه گروهی است. شروع گروه ها با یک علامت سؤال ایده آل است ، زیرا در غیر این صورت اگر می خواستید نقطه های تکمیلی را در یک گروه منطبق کنید ، لازم نیست بدون هیچ دلیل خوبی از آنها فرار کنید. اما شما همیشه باید از علامت سؤالات در Regex فرار کنید.

همچنین می توانید برای راحتی ، هنگام کار با خروجی ، گروه های خود را نام ببرید:

 (؟ 'group') 

این موارد را در Regex خود ارجاع دهید ، و این باعث می شود آنها مانند متغیرها کار کنند. شما می توانید گروههای نامبرده را با نشانه 1 ارجاع دهید ، اما این فقط تا 7 می رسد ، پس از آن شما باید گروه های نامگذاری را شروع کنید. نحو ارجاع گروه های نام گذاری شده به این شرح است:

  k {group 00 

این ارجاع به نتایج گروه نام گذاری شده است ، که می تواند پویا باشد. در اصل ، این بررسی می کند که گروه چند بار اتفاق بیفتد اما به موقعیت اهمیت نمی دهد. به عنوان مثال ، این می تواند مورد استفاده قرار گیرد تا تمام متن بین سه کلمه یکسان مطابقت داشته باشد:

کلاس گروه جایی است که شما بیشتر ساختار کنترل Regex را پیدا خواهید کرد ، از جمله کلاه های چشم. سرچشمه ها اطمینان می یابند که یک عبارت باید مطابقت داشته باشد اما در نتیجه آن را شامل نمی شود. به طریقی ، شبیه به جمله اگر است و اگر غلط برگردد ، مطابقت نخواهد داشت.

نحو یک نگاه مثبت است (؟ =) . به عنوان مثال:

با متوقف کردن اجرای در تقسیم @ این قسمت با نام آدرس ایمیل بسیار تمیز مطابقت دارد. Lookaheads هیچ کاراکتری را مصرف نمی کند ، بنابراین اگر می خواهید بعد از موفقیت در جستجوی کار خود ادامه دهید ، می توانید با شخصیت مورد استفاده در lookahead مطابقت داشته باشید.

علاوه بر سرهای نگاه مثبت ، موارد زیر نیز وجود دارد:

  • ) – نگاه های منفی ، که اطمینان می دهند یک عبارت مطابقت ندارد مطابقت ندارد.
  • (؟ <=) – نگاه های مثبت ، که به دلیل برخی محدودیت های فنی پشتیبانی نمی شوند. اینها قبل از عبارت مورد نظر برای مطابقت با شما قرار داده شده است ، و آنها باید دارای یک عرض ثابت باشند (یعنی ، هیچ شماره ای به جز {شماره} ) ندارید. w + . w + برای مطابقت با قسمت دامنه ایمیل.
  • (؟ <!) – نگاههای منفی ، که همان نگاه های مثبت هستند اما منفی هستند.

تفاوت بین موتورهای Regex

همه Regex با هم برابر نیستند. بسیاری از موتورهای Regex از استاندارد خاصی پیروی نمی کنند و برخی از آنها برای متناسب بودن با زبان خود کمی تغییر می دهند. برخی ویژگی هایی که به یک زبان کار می کنند ممکن است به زبان دیگری کار نکند.

به عنوان مثال ، نسخه های sed کامپایل شده برای macOS و FreeBSD از استفاده از t پشتیبانی نمی کند تا یک کاراکتر زبانه را نشان دهد. شما باید یک شخصیت زبانه را کپی کنید و آن را در ترمینال قرار دهید. از یک برگه در خط فرمان استفاده کنید sed .

بیشتر این آموزش با PCRE ، موتور پیش فرض Regex سازگار است. مورد استفاده برای PHP. اما موتور Regex جاوا اسکریپت متفاوت است – از گروه های اسیر شده با علائم پشتیبانی نمی کند (می خواهد براکت داشته باشد) و از جمله موارد دیگر نمی تواند بازگشت را انجام دهد. حتی PCRE کاملاً با نسخه های مختلف سازگار نیست ، و تفاوت های زیادی با Perl regex دارد.

تفاوت های جزئی زیادی در اینجا وجود دارد ، بنابراین می توانید از این جدول مرجع برای مقایسه تفاوت های بین موتورهای چند Regex استفاده کنید. همچنین ، اشکال زدایی های Regex مانند Regex101 به شما امکان می دهند موتورهای Regex را تغییر دهید ، بنابراین اطمینان حاصل کنید که با استفاده از موتور صحیح اشکال زدایی می کنید.

How To Run Regex

ما در مورد بخش تطبیق عبارات معمولی بحث کرده ایم ، که بیشترین کاربرد را دارد از آنچه Regex می کند اما وقتی واقعاً می خواهید Regex خود را اجرا کنید ، باید آن را به صورت کاملاً منظم شکل دهید.

این معمولاً به این فرمت نیاز دارد:

 / match / g 

همه چیز در داخل اسلش های جلو ، مطابقت ما است. . g اصلاح کننده حالت است. در این حالت ، به موتور می گوید که پس از یافتن اولین مسابقه ، کار خود را متوقف نکند. برای پیدا کردن و جایگزین کردن Regex ، شما اغلب باید آنرا قالب بندی کنید:

 / find / جایگزین / g 

این جایگزین همه پرونده ها می شود. می توانید هنگام تعویض از منابع گروه ضبط استفاده کنید که این امر Regex را در قالب بندی متن بسیار خوب می کند. به عنوان مثال ، این Regex با هر برچسب HTML مطابقت دارد و براکت های استاندارد را با براکت های مربع جایگزین می کند:

 / <(.+?)> / [1] / g 

با این کار ، موتور با

و مطابقت خواهد داشت.

، به شما امکان می دهد این متن را جایگزین کنید (و فقط این متن). همانطور که مشاهده می کنید ، HTML داخلی بی تأثیر است:

این باعث می شود Regex برای یافتن و جایگزینی متن بسیار مفید باشد. ابزار خط فرمان برای انجام این کار sed است که از قالب اصلی فایل:

 sed '/ find / جایگزین / g' پرونده> پرونده 

استفاده می کند و به صورت خروجی STDOUT برای جایگزین کردن پرونده روی دیسک ، باید آن را به خود (به شرح زیر) نشان دهید.

Regex همچنین در بسیاری از ویرایشگرهای متن پشتیبانی می شود ، و واقعاً می تواند جریان کار شما را هنگام انجام کار دسته ای سرعت ببخشد. Vim ، Atom و VS Code همگی Regex را پیدا کرده اند و جایگزین داخلی شده اند.

البته Regex می تواند به صورت برنامه ای نیز مورد استفاده قرار گیرد و معمولاً در بسیاری از زبانها ساخته شده است. اجرای دقیق به زبان بستگی دارد ، بنابراین شما باید با مستندات زبان خود مشورت کنید.

برای مثال ، در جاوا اسکریپت می توانید regex به معنای واقعی کلمه یا به صورت پویا با استفاده از شیء جهانی RegExp ایجاد شود:

 var re = new RegExp ('abc') 

این می تواند مستقیماً با فراخوانی روش .exec () از شیء regex تازه ایجاد شده یا با استفاده از محل جایگزین () ، .match () و .matchAll () روشها را بر روی رشته ها.