Anophel-آنوفل آموزش و بررسی عبارت منظم در PHP

آموزش و بررسی عبارت منظم در PHP

انتشار:
0
0

Regular Expression یا همان عبارت های منظم بسیار قدرتمند هستند، اما خوانا نیستند و در اغلب اوقات حفظ یک عبارت منظم کار ساده ای نیست.IDE ها می تواند کمک بیشتری در این مورد برای شما داشته باشند. ما در اینجا برای بهبود و نوشتن بهتر عبارات منظم که در PHPوجود دارد یک سری نکات بیان خواهیم کرد. البته توجه داشته باشید که این نکات ممکن است در PHP کمتر از ورژن 7 کار نکند.

 

قبل از اینکه بخواهیم نکات Regular Expression را بگویم ابتدا یک مروری بر روی آن داشته باشیم. Regular Expression یعنی چی؟

یک Regular Expression، دنباله ای از کاراکترها است که یک الگوی جستجو را تشکیل می دهد. وقتی داده‌ها را در یک متن جستجو می‌کنید، می‌توانید از این الگوی جستجو 

برای توصیف آنچه جستجو می‌کنید استفاده کنید. 

 

1. انتخاب جدا کننده (Choice of Delimiter) :

هر عبارت منظم دارای دو بخش است: عبارت(Expression) و پرچم(Flags). عبارت منظم در دو کاراکتر و به دنبال آن پرچم های اختیاری قرار می گیرد.

عبارت منظم زیر را در نظر بگیرید:

/(foo|bar)/i

در هر عبارت منظم، یک کاراکتر جداکننده حاوی عبارت و به دنبال آن پرچم‌های اختیاری است.

 جداکننده می باشد. /  یک پرچم یا تغییر کننده می باشد. و کاراکتر  i  خود عبارت می باشد. و (foo|bar)در مثال بالا 

 

 و .. باشد.~, !, @, #, $  اغلب به عنوان جدا کننده استفاده می شود.اما شما می توانید هر کاراکتری مانند , /اسلش های روبه جلو 

ولی کاراکتر های حروف عددی مانند (A-Z , a-z , 0-9 ) و حتی کاراکتر های چند بیتی (مثل ایموجی ها) و بک اسلش \ مجاز نیست که به عنوان جدا کننده از آن استفاده کنید.

 استفاده کرد  {} , () , [] , <>از بریس ها ( Braces) نیز می توانید به عنوان جداکننده استفاده کرد . عبارت های منظم با 

و بستگی به کانتکس (Context) ممکن است خوانا تر باشد.

انتخاب جداکننده بسیار مهم است زیرا باید از تمام رخدادهای کاراکتر جداکننده در عبارت فرار کرد. هر چه تعداد کاراکترهای فرار از یک عبارت منظم کمتر باشد، خواناتر خواهد بود. عدم انتخاب کاراکترهای متا (مانند ^، $، پرانتز و سایر کاراکترهایی که در عبارات منظم دارای معنای خاصی هستند) می تواند تعداد کاراکترهایی را که فرار می کنند کاهش دهد.

اگرچه اسلش های رو به جلو به عنوان یک جداکننده عبارات منظم رایج است، اما اغلب برای عبارات منظم حاوی URI مناسب نیست.

 

preg_match('/^https:\/\/anophel\.com\/path/i', $uri);

 

اسلش‌های رو به جلو (/) انتخاب ضعیفی برای جداکننده در مثال بالا هستند، زیرا خود عبارت شامل اسلش‌های رو به جلو نیز می باشد، که اکنون باید از آن‌ها خارج شوند و در نتیجه یک قطعه نسبتاً ناخوانا ایجاد می‌شود.پس چکار کنیم که خواناتر باشد ؟ طبق نکاتی که در بالا گفته شد :

به سادگی تغییر جداکننده از / به # باعث می شود عبارت خواناتر شود زیرا دیگر هیچ کاراکتر فراری در آن وجود ندارد:

 

-: /^https:\/\/anophel\.com\/path/i
+: #^https://anophel\.com/path#i

 

 -:preg_match('/^https:\/\/anophel\.com\/path/i', $uri);
 +:preg_match('#^https://anophel\.com/path#i', $uri);

 

2.کاهش کاراکتر های فرار (Reducing escape characters) :

با برداشتن یک گام بیشتر از انتخاب یک جداکننده بهتر، رویکردهای دیگری برای کاهش تعداد کاراکترهای فرار استفاده شده در یک عبارت منظم وجود دارد.

در عبارات منظم، برخی از کاراکترهای متا زمانی که در داخل پرانتزهای مربعی (کلاس کاراکتر) استفاده می شوند، کاراکتر متا در نظر گرفته نمی شوند. 

، کاراکترهای (در میان دیگران) دارای عملکرد خاصی در عبارات منظم هستند، اما نه در داخل پرانتزهای مربعی. .، *، + و $به عنوان مثال

 

/Username: @[a-z\.0-9]/

در عبارت بالا، کاراکتر نقطه (.) با یک بک اسلش (\.) خارج می شود، اما غیرضروری است، زیرا کاراکتر. وقتی در داخل پرانتزهای مربعی استفاده می شود، یک کاراکتر متا نیست.

 

علاوه بر این، برخی از کاراکترها اگر بخشی از یک محدوده نباشند، نیازی به فرار ندارند.

 

به عنوان مثال، کاراکتر خط تیره - اگر بین دو کاراکتر استفاده شود، یک محدوده کاراکتر را تعیین می کند، اما اگر در جای دیگری استفاده شود، هیچ عملکرد خاصی ندارد. در عبارت منظم /[A-Z]/، کاراکتر خط تیره - برای ایجاد طیفی از موارد منطبق از A تا Z استفاده می شود. اگر کاراکتر خط تیره /[A\-Z]/ خارج شود، عبارت منظم فقط با کاراکترها مطابقت دارد. A، Z و - . به جای فرار از کاراکتر خط تیره \-، به سادگی انتقال کاراکتر خط تیره به انتهای پرانتزهای مربع، تعداد کاراکترهایی را که نیاز به فرار دارند کاهش می دهد. عبارت منظم /[A\-Z]/ معادل [AZ-] است، اما دومی خواناتر است.

 

استفاده بیش از حد از کاراکترهای فرار( escape ) باعث نمی شود که عبارت منظم از کار بیفتد، اما می توانند تا حد زیادی خوانایی را کاهش دهند.

 

-: /Price: [0-9\-\$\.\+]+/
+: /Price: [0-9$.+-]+/ 

 

یک پرچم X وجود دارد که در صورت فرار از یک کاراکتر بدون معنای خاص، عبارت منظم را با خطا مواجه می‌کند، اما به متن حساس نیست (مثلاً پرتاب کردن یک خطا بسته به پرانتز و غیره).

 

preg_match('/x\yz/X', ''); // "y" is not a special character, but escaped.

 

Warning: preg_match(): Compilation failed: unrecognized character follows \ at offset 2 in ... on line ...

 

 

3.گروه های Non-capture

در عبارات منظم، پرانتزهای () یک گروه گرفتن را شروع می کنند. نتایج مطابق به لیست تطبیق ارسال می شود:

مثالی از عبارت منظم را در نظر بگیرید که قیمت را از یک متن داده شده، از متن استخراج می کند:Price: $20

 

$pattern = '/Price: (£|$)(\d+)/';
$text    = 'Price: $20';
preg_match($pattern, $text, $matches);

در قطعه بالا، دو گروه capture وجود دارد: گروه اول برای ارز (£|$) و به دنبال آن مقدار عددی است.

متغیر matches$ نتایج منطبق از هر دو گروه capture را ذخیره می کند:

 

var_dump($matches);
array(3) {
  [0]=> string(12) "Price: $20"
  [1]=> string(3) "$"
  [2]=> string(2) "20"
}

در مورد عبارات معمولی که اصلاً نیازی به capture ندارند، یا تعداد مطابقت‌های ارسال شده به آرایه matches$ را محدود می‌کنند، یک گروه غیرقابل جذب می‌تواند کمک کند.

سینتکس یک گروه Non-capture پرانتز است که با (?:، و به پایان می رسد). موتور Regex عبارت را در داخل بریس‌ها بیان می‌کند، اما به عنوان یک تطابق برگردانده نمی‌شود. یعنیNon-capture

 

اگر عبارت بالا فقط به مقدار عددی علاقه دارد، گروه ثبت کننده (£|$) را می توان به یک گروه غیرقابل تبدیل تبدیل کرد: (?:£|$).

 

$pattern = '/Price: (?:£|$)(\d+)/';
$text    = 'Price: $20';
preg_match($pattern, $text, $matches);
var_dump($matches);

 

array(2) {
  [0]=> string(12) "Price: $20"
  [1]=> string(2) "20"
}

 

در عبارات منظم با چندین گروه، تبدیل عبارات استفاده نشده به گروه‌های غیرقابل جذب می‌تواند مقدار داده‌های اختصاص داده شده به متغیرmatches$ را کاهش دهد.

 

 

4.Named Captures

شبیه به گروه‌هایNon-capture، کپچرهای نام‌دار این امکان را فراهم می‌کند که یک گروه خاص را گرفته و نامی برای آن بگذاریم. آنها نه تنها می توانند در نامگذاری مقادیر برگشتی کمک کنند، بلکه می توانند قسمت های خود عبارت منظم را نیز نامگذاری کنند.

 

با استفاده از همان مثال تطبیق قیمت در بالا، یک گروه capture نامگذاری شده اجازه می دهد تا نامی را برای هر گروه capture قرار دهد:

 

/Price: (?<currency>£|$)(?<price>\d+)/

 

یک گروه کپچر نامگذاری شده دارای سینتکس (?<، به دنبال نام گروه و پایان آن با ) است.

 

در مثال بالا، (?<currency>£|$) یک گروه کپچر نامگذاری شده، با ارز نامگذاری شده است، و (?<price>\d+) قیمت نامگذاری شده است. نام ها هنگام خواندن عبارت منظم کمی زمینه را فراهم می کنند، اما همچنین راهی برای نام گذاری مقادیر در آرایه مقادیر همسان ارائه می دهند.

 

$pattern = '/Price: (?<currency>£|$)(?<price>\d+)/';
$text    = 'Price: $20';
preg_match($pattern, $text, $matches);
var_dump($matches);

 

array(5) {
 [0]=> string(12) "Price: $20"
 ["currency"]=> string(3) "$"
 [1]=> string(3) "$"
 ["price"]=> string(2) "20"
 [2]=> string(2) "20"
}

آرایه matches$ اکنون حاوی نام ها و مقادیر موقعیتی مقادیر مطابقت شده است.

 

استفاده از گروه‌های capture نام‌گذاری شده، مصرف مقادیر matches$ را آسان می‌کند و بعداً با حفظ نام گروه capture، عبارت منظم را به راحتی تغییر می‌دهد.

 

به طور پیش‌فرض، گروه‌های capture با نام‌های تکراری مجاز نیستند و منجر به خطا می‌شوند

 

PHP Warning: preg_match(): Compilation failed: two named subpatterns have the same name (PCRE2_DUPNAMES not set) at offset ... in ... on line ...

این امکان وجود دارد که به صراحت به این گروه‌های کپچر با نام تکراری با اصلاح‌کننده J اجازه دهید:

 

/Price: (?<currency>£|$)?(?<price>\d+)(?<currency>£|$)?/J'

با این عبارت منظم، دو گروه capturing با نام ارز وجود دارد و به صراحت با پرچم J مجاز است. وقتی با یک رشته تطبیق داده می‌شود، فقط آخرین تطابق را برای مقدار ثبت نام‌گذاری شده برمی‌گرداند، اما مقادیر موقعیتی (0، 1، 2، ...) شامل همه مطابقت‌ها هستند.

 

$pattern = '/Price: (?<currency>£|$)?(?<price>\d+)(?<currency>£|$)?/J';
$text    = 'Price: $20£';
preg_match($pattern, $text, $matches);
var_dump($matches);
array(6) {
  [0]=> string(14) "Price: $20£"
  ["currency"]=> string(2) "£"
  [1]=> string(3) "$"
  ["price"]=> string(2) "20"
  [2]=> string(2) "20"
  [3]=> string(2) "£"
}

 

نکات دیگری نیز وجود دارند که در مقاله های دیگر در همین وب سایت آنوفل پیدا خواهید کرد.

 

اگر می خواهید با زبان PHP به صورت پیشرفته یاد بگیرید می توانید از آموزش پیشرفته PHP وب سایت آنوفل استفاده کنید.

#regex#عبارت_منظم#regular_expression#php
نظرات ارزشمند شما :
Loading...