برنامه نویسی 54 بازدید

«عبارت‌های منظم» (Regular Expressions) که اصطلاحاً regex یا regexp نامیده می‌شوند در زمان استخراج اطلاعات از هر متنی کاملاً مفید هستند. این عبارت‌ها برای جستجو و یافتن مطابقت یک یا چند الگوی جستجوی خاص مورد استفاده قرار می‌گیرند. بدین ترتیب می‌توان توالی خالصی از کاراکترهای ASCII یا یونیکد را یافت. زمینه‌های کاربرد regex از اعتبارسنجی تا تجزیه/جایگزینی رشته‌ها، ترجمه داده‌ها به قالب‌های دیگر و وب اسکرپینگ متفاوت است.

یکی از جالب‌ترین قابلیت‌های Regex این است که پس از یادگیری ساختار آن می‌توانید در تقریباً همه زبان‌های برنامه‌نویسی شامل JavaScript ،Java ،VB ،C# ،C / C++ ،Python ،Perl ،Ruby ،Delphi ،R ،Tcl و بسیاری دیگر استفاده کنید. تنها تفاوت در این است که برخی زبان‌ها از برخی قابلیت‌های پیشرفته‌تر و نسخه‌های ساختار متفاوت پشتیبانی می‌کنند.

در ادامه برخی نمونه‌ها را مورد بررسی قرار داده و در مورد هر کدام توضیح می‌دهیم.

موضوعات ابتدایی Regex

در این بخش برخی موضوعات کاملا مقدماتی مرتبط با regex را مورد بررسی قرار می‌دهیم.

مهارها – ^ و $

  • The^ – با هر رشته‌ای که با The آغاز شود تطبیق می‌یابد.
  • $end – با هر رشته‌ای که به کلمه end خاتمه یابد تطبیق می‌یابد.
  • $The end^ – تطبیق دقیق رشته‌ای را تعریف می‌کند، یعنی رشته مورد جستجو باید با The آغاز و با end خاتمه یابد.
  • roar  – با هر رشته‌ای که کلمه roar در آن باشد تطبیق می‌یابد.

سورها – * + ? و {}

  • *abc – با هر رشته‌ای که در ابتدایش کاراکترهای ab و در ادامه صفر یا چند c داشته باشد تطبیق می‌یابد.
  • +abc – با هر رشته‌ای که در ابتدایش کاراکترهای ab و در ادامه یک یا چند کاراکتر c داشته باشد تطبیق می‌یابد.
  • ?abc – با هر رشته‌ای که در ابتدایش کاراکترهای ab و در ادامه صفر یا یک کاراکتر c داشته باشد تطبیق می‌یابد.
  • {abc{2 با هر رشته‌ای که در ابتدایش کاراکترهای ab و در ادامه دقیقاً 2 کاراکتر c داشته باشد تطبیق می‌یابد.
  • {,abc{2 با هر رشته‌ای که در ابتدایش کاراکترهای ab و در ادامه 2 یا بیشتر کاراکتر c داشته باشد تطبیق می‌یابد.
  • {abc{2,5 با هر رشته‌ای که در ابتدایش کاراکترهای ab و در ادامه 2 تا 5 کاراکتر c داشته باشد تطبیق می‌یابد.
  • *(a(bc – با هر رشته‌ای که در ابتدایش کاراکتر a و در ادامه صفر یا چند کپی از دنباله bc داشته باشد تطبیق می‌یابد.
  • {a(bc){2,5 با هر رشته‌ای که در ابتدایش کاراکتر a و در ادامه 2 تا 5 کپی از دنباله bc داشته باشد تطبیق می‌یابد.

عملگر OR – | یا []

  • (a(b|c – با هر رشته‌ای که یک کاراکتر a و در ادامه b یا c داشته باشد تطبیق می‌یابد.
  • [a[bc – همانند regex قبلی است.

دسته‌های کاراکتر – d \w \s\ و .

  • d\ – با یک کاراکتر منفرد که رقم باشد تطبیق می‌یابد.
  • w\ – با یک کاراکتر کلمه (کاراکتر حرفی/عددی به علاوه زیرخط) تطبیق می‌یابد.
  • s\ – با کاراکتر خالی تطبیق می‌یابد (شامل tab و line break نیز می‌شود).
  • . – با هر کاراکتری تطبیق می‌یابد.

باید از عملگر  (.) با احتیاط استفاده کنید، چون در اغلب موارد کلاس یا کلاس کاراکتر منفی آن (که در ادامه معرفی می‌کنیم) سریع‌تر و بسیار دقیق‌تر است. حالت نفی d ،\w\ و s\ به ترتیب D ،\W\ و S\ هستند. برای نمونه D\ تطبیق معکوس را با توجه به آن چیزی که با d\ به دست می‌آید ارائه می‌کند.

  • D\ – با یک کاراکتر غیر رقمی منفرد تطبیق می‌یابد.

برای این که به صورت عملی از آن استفاده کنید، باید کاراکترها را با استفاده از \ به صورت escape درآورید چون معنای خاصی دارند.

  • d\$\ – با رشته‌ای تطبیق می‌یابد که یک $ پیش از یک رقم دارد.

توجه کنید که می‌توانید کاراکترهای غیر قابل چاپ مانند t\، خطوط جدید n\، بازگشت‌های carriage یعنی r\ را نیز تطبیق دهید.

فلگ‌ها

تا به این جا در مورد شیوه ساخت یک regex مطالبی آموختیم، اما یک مفهوم بنیادی به نام فلگ را فراموش کرده‌ایم.

Regex معمولاً به صورت /abc/ ارائه می‌شود که الگوی جستجو به وسیله دو کاراکتر اسلش متمایز شده است. در انتهای عبارت منظم می‌توان یک فلگ با مقادیر زیر تعیین کرد (امکان ترکیب کردن آن‌ها با هم نیز وجود دارد):

  • g (سراسری یا global) – پس از نخستین تطبیق بازگشت نمی‌یابد و جستجوهای بعدی را از انتهای مورد مطابقت قبلی آغاز می‌کند.
  • m (چندخطی یا multi-line) – زمانی که ^ و $ به جای کل رشته با ابتدا و انتهای یک خط مطابقت داشته باشند.
  • i (غیر حساس یا insensitive) – موجب می‌شود که کل عبارت منظم از حالت حساس به حروف کوچک یا بزرگ خارج شود. برای نمونه aBc/i/ می‌تواند با AbC تطبیق یابد.

موضوعات سطح متوسط

در این بخش برخی مباحث regex را بررسی می‌کنیم که فراتر از سطح مقدماتی قبلی هستند، اما هنوز وارد حیطه پیشرفته نشده‌ایم.

گروه‌بندی و capture – ()

  • (a(bc – پرانتزها یک گروه تشکیل می‌دهند که مقدار bc را به دست می‌دهد.
  • *(a(?:bc – ما با استفاده از : ? گروه capturing را غیر فعال می‌کنیم.
  • (a(?<foo>bc – با استفاده از <foo>? یک نام برای گروه خود تعیین می‌کنیم.

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

اگر بخواهیم برای گروه‌های خود نام‌گذاری کنیم، می‌توانیم مقادیر گروه را با استفاده از نتیجه تطبیق یافته مانند یک دیکشنری به دست آوریم که در آن کلیدها نام هر گروه خواهند بود.

عبارت‌های براکت – []

  • [abc] – با هر رشته‌ای که یک a یا ab یا a c داشته باشد، تطبیق می‌یابد و معادل a|b|c است.
  • [a-c] همانند قبلی است.
  • [a-fA-F0-9] – با رشته‌ای تطبیق می‌یابد که نماینده یک رقم هگزادسیمال منفرد است و حساسیت به حروف کوچک یا بزرگ ندارد.
  • [0-9]%  – با رشته‌ای تطبیق می‌یابد که پیش از علامت % یک کاراکتر از 0 تا 9 دارد.
  • [^a-zA-Z] – با رشته‌ای تطبیق می‌یابد که حرفی از a تا z یا از A تا Z ندارد. در این حالت ^ به عنوان منفی عبارت استفاده می‌شود.

به خاطر داشته باشید که درون عبارت‌های براکتی، همه کاراکترهای خاص (شامل بک اسلش \) قدرت خاص خود را از دست می‌دهند. بدین ترتیب قاعده scape قابل استفاده نیست.

تطبیق Greedy و Lazy

سورها یعنی * + {} عملگرهای حریص (Greedy) هستند، بنابراین مورد تطبیق را تا آنجا که ممکن است روی متن مورد نظر گسترش می‌دهند.

برای نمونه <+.> با <div>simple div</div> در عبارت This is a <div> simple div</div> test تطبیق می‌یابد. برای این که تنها تگ div تطبیق یابد، می‌توانیم از یک ? استفاده کنیم تا آن را تنبل (Lazy) کنیم:

  • <?+.> – با هر کاراکتری که یک یا چند بار درون < و > آمده باشد تطبیق می‌یابد و در صورت نیاز گسترش می‌یابد.

توجه داشته باشید که یک راه‌حل بهتر عدم استفاده از . به نفع یک regex صریح‌تر است:

  • <+[<>^]> –  با هر کاراکتری به جز > یا < که یک یا چند بار درون < و > قرار داشته باشد تطبیق می‌یابد.

موضوعات پیشرفته

در این بخش، برخی مباحث پیشرفته مرتبط با regex را مورد بررسی قرار می‌دهیم.

کران‌ها b\ و B\

babc\b\ – یک جستجوی «صرفاً کل کلمه» اجرا می‌کند.

b\ نشان‌دهنده یک مهار مانند caret است (مشابه $ و ^ است) و با موقعیت‌هایی تطبیق می‌یابد که یک طرف یک کاراکتر کلمه (مانند w\) است و طرف دیگر کاراکتر کلمه نیست، مثلاً می‌تواند ابتدای یک رشته یا یک کاراکتر فاصله باشد.

حالت نفی این کران به صورت B\ است. این کران با همه موقعیت‌های تطبیق می‌یابد که b\ تطبیق پیدا نکند و می‌توان از آن برای یافتن الگوی جستجویی استفاده کرد به طور کامل در کاراکترهای کلمه‌ای احاطه شده است.

Babc\B\ تنها در صورتی تطبیق می‌یابد که الگو به صورت کامل در کاراکترهای کلمه احاطه شده باشد.

ارجاع به عقب  1\

([abc])\1 

استفاده از 1\ موجب می‌شود که نتیجه با همان متنی تطبیق پیدا کند که در گروه نخست capture مطابقت یافته است.

([abc])([de])\2\1 

می‌توان از 2\ (3\، 4\ و غیره) نیز برای شناسایی همان متنی که در گروه capture مورد دوم (سوم و چهارم و غیره) تطبیق می‌یابد استفاده کرد.

(?<foo>[abc])\k<foo> 

می‌توان نام foo را روی گروهی قرار داد و آن را بعداً مورد اشاره قرار داد. نتیجه همان regex نخست است.

گشتن در سمت جلو و عقب (=?) و (=>?)

d(?=r)

با یک d تنها در صورتی تطبیق می‌یابد که در ادامه r آمده باشد، اما r بخشی از تطبیق regex کلی نخواهد بود.

(?<=r)d

تنها در صورتی با یک d تطبیق پیدا می‌کند که قبل از آن یک r آمده باشد، اما r جزئی از تطبیق regex کلی نخواهد بود.

همچنین می‌توان از عملگر نفی نیز استفاده کرد:

d(?!r)

تنها در صورتی با یک d تطبیق می‌یابد که در ادامه r نیامده باشد، اما r بخشی از تطبیق regex کلی نخواهد بود.

(?<!r)d

تنها در صورتی با یک d تطبیق پیدا می‌کند که قبل از آن یک r نیامده باشد، اما r جزئی از تطبیق regex کلی نخواهد بود.

جمع‌بندی

چنان که دیدیم کاربردهای اپلیکیشن regex می‌توانند کاملاً متنوع باشند. مطمئناً شما دست کم یکی از این وظایف را تاکنون در زمان اجرای وظایف توسعه نرم‌افزار خود مشاهده کرده‌اید. در ادامه این کاربردها را در یک فهرست خلاصه جمع‌بندی کرده‌ایم.

  • اعتبارسنجی داده – برای نمونه آیا یک رشته زمانی به درستی ترکیب یافته است یا نه.
  • کاوش داده – به خصوص وب اسکرپینگ که در آن همه صفحه‌هایی که شامل مجموعه خاص از کلمات هستند در نهایت با ترتیب خاصی پیدا می‌شوند.
  • دستکاری داده‌ها – تبدیل داده از قالب خام به یک قالب دیگر.
  • تجزیه متن – برای نمونه گردآوری همه پارامترهای GET در URL و دریافت یک متن که درون یک مجموعه از پرانتزها قرار دارد.
  • جایگزینی رشته – برای نمونه در زمان کدنویسی در یک IDE برای ترجمه کلاس جاوا به سی شارپ در شیء JSON متناظر باید (;) با (,) جایگزین شوند، به حالت حروف کوچک درآید و hc اعلان نوع خودداری شود.
  • هایلایت کردن ساختار، تغییر دادن نام فایل‌ها، بررسی بسته‌ها و بسیاری کاربردهای دیگر که با رشته‌ها سرور کار دارند و داده‌ها باید متنی باشد، همگی با استفاده از regex قابل اجرا هستند.

اگر این مطلب برای شما مفید بوده است، آموزش‌های زیر نیز به شما پیشنهاد می‌شوند:

==

telegram
twitter

میثم لطفی

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

بر اساس رای 1 نفر

آیا این مطلب برای شما مفید بود؟

نظر شما چیست؟

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *