به کمک عبارات منظم در برنامهنویسی میتوانیم در یک رشته متنی الگوهای مورد نظر را بررسی کنیم. از عبارت منظم در PHP برای پیدا کردن الگوهای خاص یا اعتبارسنجی مقادیر رشتهای استفاده میشود. در این آموزش با الفبای اصلی Regex در PHP آشنا شده و توابع آن را یاد میگیریم.
در ابتدا کار بهتر است دقیقتر بفهمیم منظورمان از الگو (pattern) چیست ؟ با دو مثال هدف استفاده از ریجکس در php را توضیح میدهم.
فرض کنید یک متن در اختیار دارید و میخواهید وضعیت تکرار یک کلمه خاص در آن را بررسی کنید. مثلاً میخواهیم ببینیم کلمه «سبز دانش» چند بار در آن به کار برده شده است. این کار را میتوانیم با روشهای کار با رشته هم انجام دهیم.
ولی اگر کلمه مورد نظر ما پیچیدهتر باشد چه ؟ مثلاً بخواهیم تعداد تکرار عبارتهایی را پیدا کنیم که با «س» شروع شده و با «نش» پایان مییابد. برای این کار مجبوریم از عبارتهای منظم استفاده کنیم.
به همین شکل فرض کنید در یک فرم PHP فیلدی برای دریافت ایمیل دارید. ساختار ایمیل مشخص است اما تعداد حروف و حروف استفاده شده در آن برای هر نفر متفاوت است. برای اینکه مقدار وارد شده را اعتبارسنجی کنیم، از عبارات منظم در php استفاده خواهیم کرد.
تا به اینجا فهمیدیم که عبارت منظم چیست و چرا به دنبال یافتن آن هستیم. در ادامه با ساختار عبارات منظم و الفبای استفاده شده در آن میپردازیم و در انتها نیز توابع مهم Regex در PHP را بررسی خواهیم کرد.
فهرست محتوای آموزش
عبارت منظم در PHP
بحث عبارات منظم یا Regular Expression فقط محدود به PHP نیست! در دروس رشته کامپیوتر یک ترم در مورد عبارات و ماشینهای منظم صحبت میشود. معنا و مفهوم Regex (مخفف عبارات منظم) در همه جا یکسان است.
در اکثر زبانهای برنامهنویسی سطح بالا توابعی برای بررسی ریجکسها تعریف شدهاند. الفبای تعریف یک عبارت منظم، در اکثر این زبانها یکسان است. دلیل آن هم یادگیری و هماهنگی بیشتر میان زبانهاست.
سعی میکنم در این آموزش مفاهیم و علائم اصلی را بررسی کرده و لینکهای مرجعی برای مطالعه بیشتر به شما ارائه کنم.
در یادگیری عبارات منظم در PHP دو مرحله اصلی داریم:
- تعریف الگو یا عبارت منظم
- استفاده از توابع عبارات منظم
ساختار عبارات منظم php
عبارت منظم در php یک رشته متنی است که از سه بخش اصلی تشکیل شده است: جداکننده، الگو و اصلاحکنندههای اختیاری.
$exp = "/sabzdanesh/i";
در عبارت منظم بالا علامت /
به عنوان جداکننده (delimiter)، کلمه sabzdanesh
الگوی مورد نظر (pattern) و i
یک اصلاحکننده (modifier) است که مشخص میکند الگوی ما به کوچکی یا بزرگی حروف حساس نیست.
جداکننده میتواند هر کاراکتری غیر از حروف، اعداد، فاصله (space) و \
باشد. معمولاً از علامت اسلش (/
) در عبارات منظم استفاده میشود. اما در جاهایی که الگو دارای علامت slash هست از جداکنندههای دیگر (مثل #
یا ~
) استفاده میشود.
الفبای عبارت منظم PHP
همانطور که گفتم، عبارات منظم یک زبان یا قاعده هستند. مانند هر زبان دیگری، عبارات منظم از الفبایی برای تعریف الگو استفاده میکند. میتوان گفت باید این علائم را حفظ کنیم! البته به قدری ساده و مفهوم هستند که با چند بار استفاده از آنها، بتوانیم یک Regex بنویسیم.
متاکاراکترها در ریجکس PHP
از متاکاراکترها (Meta Characters) برای مشخص کردن ویژگی همه یا بخشی از الگو استفاده میشود.
پر استفادهترین علائم متا عبارتاند از:
^
برای مشخص کردن شروع یک رشته متنی$
برای مشخص کردن پایان رشته متنی.
(نقطه) یک کاراکتر نامشخص (هر کاراکتری میتواند جایگزین این علامت شود)\
اگر در الگو از علائم خاص Regex وجود داشت، با قرار دادن\
قبل از آن کاراکتر، معنای ریجکسی آن را بیمعنا میکنیم.|
به معنی «یا» بین کاراکترها استفاده میشود.
علامت نقطه به معنی وجود یک کاراکتر به جای آن است. یک عبارت منظم که مشخص کننده یک کلمه سه کاراکتری است به صورت /.../
تعریف میشود. این الگو برای abc
یا s3e
یا u%3
صدق خواهد کرد.
تعریف کاراکتر در عبارت منظم php
کاراکترها تقریباً اصلیترین بخش یک عبارت منظم در PHP هستند. کاراکترها را میتوان به صورت دقیق با به کار بردن همان کاراکتر در الگو تعریف کرد. برای مثال /ab/
الگویی است که یک کلمه دو حرفی ab را مشخص میکند.
کاراکترهای حروفی به صورت a و b و c تا z و عددی به صورت 0 و 1 تا 9 مشخص میشوند. چون حروف انگلیسی حساس به کوچکی و بزرگی هستند، مجموعه A تا Z را هم برای تعریف کاراکتر با حرف بزرگ در اختیار داریم.
در صورت نیاز میتوان از کاراکترهای دیگر، مثل @
یا .
هم استفاده کنیم. فقط توجه داشته باشید که اگر این کاراکتر جزء علائم Meta بود، قبل از آنها از \
استفاده کنیم.
علامت .
علامتی است که مشخصکننده فقط و فقط یک کاراکتر است.
گروهبندی و محدوده کاراکترها
واضح است که برای کاربردهای پیچیده، استفاده از خود کاراکتر بی معنا خواهد شد. بنابراین به کمک ۳ علامت مختلف، برای کاراکترها یک محدوده مشخص کرده یا آنها را به صورت مجموعه تعریف میکنیم. این علائم در جدول زیر آورده شدهاند:
– | برای مشخص کردن محدوده |
() | مشخص کننده یک گروه از کاراکترها |
[] | فقط یکی از کاراکترهای درون کروشه |
فرض کنید میخواهیم در بخشی از یک عبارت منظم، استفاده از یک حرف کوچک انگلیسی را مشخص کنیم. برای تعریف مجموعه کاراکترها از a-z
استفاده میکنیم. سپس این مجموعه را درون کروشه (قلاب) قرار میدهیم؛ به این معنی که فقط یکی از حروف این مجموعه مورد نظر ماست.
[a-z]
حال میخواهیم به جای تمام حروف انگلیسی، فقط چهار حرف s و a و b و z را داشته باشیم. کافی است این چهار حرف را کنار هم درون یک کروشه قرار دهیم.
[sabz]
عبارت منظم بالا برای عباراتی نظر s
یا b
یا z
نتیجه مثبت و برای bz
و مشابه آن جواب منفی خواهد داد.
فرض کنید میخواهیم یک عبارت با a یا b شروع شود. در ابتدای عبارت منظم مورد نظر خود در php گروه زیر را مینویسیم:
(a|b)
در این Regex از پرانتز برای گروه شدن محتوای درون آن استفاده شده است. به این عبارت پس از اتصالش به ابتدای ریجکس به صورت یک کاراکتر نگاه خواهد شد. همچنین از علامت |
برای مشخص کردن «یا» استفاده شده است.
در عبارت منظم php زیر، یک الگو تعریف شده که: با a یا b شروع میشود، سپس یکی از اعداد 3 تا 7 را دارد و در نهایت با یکی از حروف بزرگ انگلیسی پایان یافته است.
$my_regex = "/(a|b)[3-7][A-Z]/"
الگو با کمیتهای مقداری
علائم دیگری در عبارات منظم PHP داریم که به کمک آنها تعداد کاراکترها در الگو را مشخص میکنیم. این علائم پس از یک کاراکتر یا گروه کاراکتر (پرانتز یا کروشه) قرار گرفته و تعداد مجاز تکرار آن قاعده را مشخص میکند.
* | هیچ (0) یا بیشتر |
+ | تعداد 1 بار یا بیشتر |
? | دقیقاً 0 یا 1 بار |
{X} | دقیقاً X بار |
{X,} | X یا بیشتر |
{X,Y} | بین X تا Y |
اجازه دهید با چند مثال، درک این علائم را سادهتر کنم.
عبارت منظم ab+
یک رشته را مشخص میکند که حتماً با یک a شروع شده و پس از آن حداقل یک بار b قرار دارد.
عبارت منظم ab*
رشتهای را مشخص میکند که با یک a شروع شده و پس از آن به تعداد دلخواهی b دارد. یعنی a و ab و abbbbb در این الگو پذیرفته میشوند.
عبارت منظم [a-z]+
رشتهای را مشخص میکند که تماماً از حروف کوچک انگلیسی تشکیل شده و حداقل یک کاراکتر دارد.
عبارت منظم [a-z]{3,5}
رشتهای از حروف کوچک انگلیسی را مشخص میکند که حاوی ۳ یا ۴ یا ۵ کاراکتر است.
توابع مهم کار با عبارت منظم در PHP
مرحله پیچیدهتر (سختتر) کار با عبارات منظم در PHP تمام شد! حال که توانستیم یک الگوی ریجکس برای اعتبارسنجی رشته متنی خود بنویسیم، کافی است به کمک ۳ تابعی که در ادامه معرفی میشود، رشته متنی خود را ارزیابی کنیم.
بررسی وجود الگو با preg_match
تابع preg_match()
پنج پارامتر ورودی میگیرد. دو پارامتر اول اجباری و ۳ تای بعدی اختیاری است.
این تابع در ورودی اول الگوی مورد نظر و در دومین پارامتر رشتهای که باید در آن جستجو کند را دریافت میکند. اگر رشته مطابق با الگو بود، مقدار true و در غیراینصورت false به عنوان خروجی میدهد.
preg_match( string $pattern, string $subject, array &$matches, int $flags, int $offset );
ورودیهای اختیاری این تابع عبارتاند از:
- پارامتر سوم (
$matches
) جستجوهای پیدا شده را در خود نگه میدارد. باید یک آرایه به این ورودی بدهیم. - در صورت 1 قرار دادن پارامتر چهارم (
$flags
) اندیس شروع عبارات مطابق الگو را به ما برمیگرداند. - اگر بخواهیم جستجوی الگو از یک اندیس خاص به بعد در رشته انجام شود، مقدار اندیس را به عنوان ورودی آخر (
$offset
) تعریف میکنیم.
فرض کنید رشته $str
را داریم. در قطعه کد زیر، اگر کلمهای مطابق با الگوی $pattern
پیدا شد، پیام founded و در غیر اینصورت not founded چاپ میشود.
$str = "Hi! This a test for PHP Regex find from sabzdanesh site. have a nice time!";
$pattern = "/.es/";
$result = preg_match( $pattern, $str );
if( $result )
echo "pattern founded!";
else
echo "pattern not founded!";
وقتی این کد را اجرا کنیم، نتیجه نهایی founded خواهد بود. چون در دو جا (test و sabzdanesh) الگوی .es
آورده شده است.
حال برای پارامتر سوم متغیر $occurs
را قرار داده و کد را اجرا میکنیم. با این تفاوت که در صورت پیدا کردن الگو، آرایه occurs را چاپ میکنیم.
$str = "Hi! This a test for PHP Regex find from sabzdanesh site. have a nice time!";
$pattern = "/.es/";
$result = preg_match( $pattern, $str, $occurs );
if( $result )
print_r( $occurs );
else
echo "pattern not founded!";
نتیجه کد بالا چیزی شبیه زیر خواهد بود:
Array ( [0] => tes )
به نظر شما چرا در نتایج پیدا شده، دومین مقداری که با الگو مطابق داشت آورده نشده؟
تابع preg_match()
فقط اولین تطابق را پیدا کرده و آن را به عنوان نتیجه به ما بازمیگرداند.
شمارش تکرار با preg_match_all
تابع preg_match_all()
دقیقاً مشابه تابع قبلی عمل میکند با این تفاوت که همه مطابقتها را به عنوان خروجی به ما برمیگرداند.
با اجرای قطعه کد زیر، هر دو مقداری که مطابق با الگوی ما در رشته بود، در آرایه occurs قرار گرفتهاند.
$str = "Hi! This a test for PHP Regex find from sabzdanesh site. have a nice time!";
$pattern = "/.es/";
preg_match( $pattern, $str, $occurs );
print_r( $occurs );
//Output:
// Array ( [0] => tes [1] => nes )
جایگزین کردن الگو با preg_replace
در ترفندهای کار با رشته در PHP با تابعی برای جایگزینی یک کلمه با کلمهای دیگر در رشته آشنا شدیم. اگر بخواهیم مشابه همان کار را با الگوها انجام دهیم از تابع preg_replace()
استفاده خواهیم کرد.
سه پارامتر اول ورودی این تابع اجباری است. اولین پارامتر مشخصکننده الگوی جستجو، دومین پارامتر عبارتی که باید جایگزین الگو شود و سومین پارامتر رشتهای است که میخواهیم در آن عملیات جایگزینی انجام شود.
$str = "I have been used php5 for 3 years. But now i use php7 instead of.";
$pattern = "/php[3-8]/";
$result = preg_replace( $pattern, "python", $str );
با اجرای قطعه کد بالا، به جای php5 و php7 عبارت python جایگزین خواهد شد.
خروجی این تابع یک رشته متنی است که تغییرات مورد نظر ما در آن اعمال شده است.
اگر میخواهید مثالهای پیچیدهتری از عبارات منظم در php بخوانید یا با علامتهای بیشتری آشنا شوید، به صفحه مستندات آن مراجعه کنید.
این آموزش برای همیشه رایگانه! میتونید با اشتراکگذاری لینک این صفحه از ما حمایت کنید یا با خرید یه فنجون نوشیدنی بهمون انرژی بدید!
میخوام یه نوشیدنی مهمونتون کنم
سلام ممنون از مقاله خوبتون ولی یه سوال برام پیش اومده ممنون میشم منو راهنماییم کنید. شما اواسط مقاله گفتین که [a-z] فقط یک کاراکتر رو انتخاب میکنه از حروف بین a تا z. ولی پایین تر که راجب کمیت های مقداری صحبت کردین یه مثال زدین به این صورت : [a-z]{3,5} و گفتین که این عبارت رشته ای رو مشخص میکنه که حاوی سه یا چهار یا 5 کاراکتر هستش.خب این دو مطلب باهم متفاوته که ! چون کروشه به گفته شما هرچی داخلش باشه فقط یک کاراکتر رو انتخاب میکنه . ولی الان چیزی خلاف این شد ممنون میشم راهنمای کنید.
سلام
چقدر خوبه که سعی میکنید بین بخشهای مختلف آموزش ارتباط ایجاد کنید. این کار کمک میکنه خیلی بهتر یاد بگیرید 🙂
علامت کروشه، بازهای رو مشخص میکنه که از درونش فقط یه کاراکتر انتخاب میشه.
آکولاد، مقدار قبلیش رو به تعداد مشخص تکرار میکنه.
پس ما در این ریجکس داریم میگیم تعداد 3 الی 5 تا از ساختار قبلی (که یک کاراکتر بین a تا z هست) مجازه؛ یعنی 3 تا 5 تککاراکتر که میشه یک رشته.
امیدوارم با این توضیح، بحث رو بهتر متوجه شده باشین. اگه هنوزم جاییش براتون سؤاله، بپرسید تا با مثال دیگهای توضیح بدم.
ممنون متوجه شدم . فقط ممنون میشم اگه کتاب چاپی خوبی اگه سراغ دارید راجب php معرفی کنید. من یه کتاب گرفتم در بخش عبارات منظمش دو تابع
split()
وereg_replace()
رو شرح داده. ولی شما اشاره ای نکردین به این توابع . ممنون میشم نظرتونو راجبشون بدونم. خودم حس میکنم این کتاب یه مقدار آپدیت نیست و گنگ و نامفهوم توضیح داده.خواهش میکنم.
آره این دو تابعی که گفتین منسوخ شدند و مربوط به نسخههای خیلی قدیمیتر هستند.
مثلاً split رو داخل مستنداتش چک کردم از نسخه 5.3 منسوخ شده! پیشنهاد میکنم کتاب دیگهای رو استفاده کنید.
واقعیتش کتاب مناسبی که بخوام معرفی کنم در حال حاضر سراغ ندارم! شخصاً یا کتابهای پراکنده خوندم یا از مستندات و آموزشهای وب کمک گرفتم. البته سعی داریم یک نقشه راه یادگیری معرفی کنیم که حتماً کتابهایی رو باید بررسی و پیشنهاد بدیم. برای بررسی توابع حتماً از مستندات PHP کمک بگیرین.
اینستاگراممون که توی صفحه تماس با ما هست از هفته آینده شروع به فعالیت دوباره میکنه. اونجا در مورد نکات بیشتر و انتشار نقشه راهها اطلاعرسانی میکنیم. پیشنهاد میکنم فالو کنید. 😉
سلام
الگوی زیر رو ببینید:
"([A-Za-z0-9]+[.])*[A-Za-z0-9]+@gmail.com"
این الگو میتونه gmail رو در یک متن بدست بیاره. این الگو رو تو همه زبان های برنامه تست کردم و نتیجه درستی گرفتم ولی در php نتیجه ای کاملا اشتباه داده میشه:
نتیجه به صورت زیر نمایش داده شد:
سلام
مورد جالبی بود برام! تا حالا به چنین مسئلهای برنخورده بودم!
اینطور که جستجو کردم ظاهراً این تابع علاوه بر مقداری که با regex تناسب داره، تمام گروهها (که با پرانتز در عبارت منظم مشخص شدن) رو هم برمیگردونه.
برای اینکه اون گروه به عنوان یه عنصر جدید داخل آرایه نباشه، PREG_SET_ORDER رو در آرگومان چهارم بدید.
اگه راهحل مناسبی برای نادیده گرفتنشون پیدا کنم مجدد اطلاع میدم. الان با مستنداتش به همین نتیجه رسیدم. تست هم کردم درسته.
سلام بسیار عالی
من ی ریجکس دارم که پرانتز داره و مثل مثالتون نیست . داخلش فقط چندتا کاراکتر داره. میشه یکم بیشتر توضیح بدید؟ گیج شدم
سلام
پرانتز در عبارت منظم یعنی یک گروه! حالا این گروه میتونه خودش قواعد خاصی داشته باشه (مثل مثال) یا صرفاً یک عبارت چند کاراکتری باشه. مثلا
(ab)+
یعنی رشته ab حداقل یکبار وجود داشته باشه.خیلی کامل توضیح دادین. مرسی
خوشحالم برای یادگیریتون ارزش قائلین سهیلای عزیز.