ویژگی تصویر

تابع preg_match() در PHP

  /  PHP   /  تابع preg_match() در PHP
بنر تبلیغاتی الف
آموزش PHP

تابع preg_match() یکی از توابع پایه‌ای PHP برای بررسی و استخراج متن با استفاده از عبارات منظم (Regular Expressions) بر پایه PCRE است. این تابع برای چک کردن اینکه آیا یک الگو در یک رشته وجود دارد یا خیر و همچنین گرفتن گروه‌های متناظر بسیار کاربردی است.

فرم کلی و مقادیر بازگشتی

امضای ساده تابع:

int preg_match ( string $pattern , string $subject , array &$matches = null , int $flags = 0 , int $offset = 0 )

توضیح بازگشتی:

مقدارمعنی
1مطابقت پیدا شد
0هیچ مطابقتی وجود نداشت
falseخطا (مثلاً الگوی نامعتبر)

نکات کلیدی

  • الگو باید بین جداکننده‌ها (delimiters) قرار گیرد، معمولاً /pattern/.
  • برای کار با UTF-8 از مدیفایر u استفاده کنید.
  • برای فعال شدن حالت چندخطی از m و برای اینکه نقطه شامل خط جدید هم شود از s استفاده کنید.
  • برای جلوگیری از اشتباه در کاراکترهای خاص، از preg_quote() استفاده کنید.

مثال‌های عملی

1) بررسی فرمت ساده شماره موبایل (ایرانی)

$phone = '09121234567';
if (preg_match('/^09d{9}$/', $phone)) {
    echo 'Valid mobile';
} else {
    echo 'Invalid mobile';
}

در این مثال الگو بررسی می‌کند که رشته با 09 شروع شده و دقیقاً 9 رقم بعد از آن وجود دارد. اگر مطابقت وجود داشته باشد مقدار 1 بازمی‌گردد.

2) استخراج گروه‌ها (Capturing Groups)

$date = '2025-11-07';
if (preg_match('/^(d{4})-(d{2})-(d{2})$/', $date, $matches)) {
    // $matches[0] => '2025-11-07'
    // $matches[1] => '2025'
    // $matches[2] => '11'
    // $matches[3] => '07'
    print_r($matches);
}

در این کد با استفاده از پرانتزها سه گروه گرفته شده و در آرایه $matches قرار می‌گیرند. اندیس صفر همیشه متن کامل مطابقت است.

3) استفاده از Named Groups و گرفتن آفست‌ها

$text = 'Price: $123.45';
if (preg_match('/Price:s+$(?Pd+.d{2})/', $text, $m, PREG_OFFSET_CAPTURE)) {
    // $m['amount'][0] => '123.45'
    // $m['amount'][1] => offset position
    print_r($m);
}

در اینجا از named group با نام amount استفاده شده و با فلگ PREG_OFFSET_CAPTURE علاوه بر متن مطابقت، جایگاه (offset) در رشته نیز بازگردانده می‌شود.

4) کار با متن‌های فارسی و یونیکد

$name = 'علی رضایی';
if (preg_match('/^[p{L}s]+$/u', $name)) {
    echo 'Valid Persian name';
} else {
    echo 'Invalid name';
}

مد u باعث می‌شود الگو بر پایه UTF-8 پردازش شود. از کلاس کاراکتر p{L} برای تطابق هر حرف (از هر زبان) استفاده شده است و فاصله‌ها مجاز هستند.

پیدا کردن چندین مورد: تفاوت با preg_match_all()

اگر به دنبال پیدا کردن همهٔ تطابق‌ها هستید از preg_match_all() استفاده کنید. preg_match() فقط اولین تطابق را بررسی و (در صورت درخواست) ذخیره می‌کند.

$text = 'apple banana apple';
preg_match_all('/apple/', $text, $all);
print_r($all);

در این مثال preg_match_all هر دو مطابقت ‘apple’ را بازمی‌گرداند، در حالی که preg_match فقط اولین را گزارش می‌دهد.

اشتباهات رایج و راهکارها

  • فراموش کردن جداکننده (/): الگو بدون جداکننده معتبر خطا می‌دهد و تابع مقدار false بازمی‌گرداند.
  • عدم استفاده از u برای UTF-8: باعث می‌شود حروف غیرلاتین درست تشخیص داده نشوند.
  • استفاده از نقطه بدون s: نقطه به صورت پیش‌فرض خط جدید را شامل نمی‌شود.
  • برای داده‌های کاربر که ممکن است شامل کاراکترهای ویژه regex باشند از preg_quote() قبل قرار دادن در الگو استفاده کنید.

مثال preg_quote()

$keyword = 'C++';
$pattern = '/' . preg_quote($keyword, '/') . '/';
if (preg_match($pattern, 'I love C++')) {
    echo 'Found';
}

این مثال از preg_quote برای فرار دادن (+) استفاده می‌کند تا به جای معنی متادیتا در regex، به صورت متن ساده جستجو شود.

عملکرد و بهینه‌سازی

  • از الگوهای ساده‌تر و مشخص‌تر استفاده کنید؛ الگوهای بسیار عمومی و سنگین می‌توانند هزینه محاسباتی بالایی داشته باشند.
  • در صورت امکان از توابع ساده‌تر PHP (مانند strpos، substr) استفاده کنید چون سریع‌تر هستند.
  • از greedy vs lazy آگاه باشید: .* طمع‌کار است و می‌تواند نتایج غیرمنتظره یا کندی ایجاد کند؛ از .*? برای کمینه‌گرا استفاده کنید.

مثال کامل: بررسی ایمیل با هشدار

$email = 'user@example.com';
$pattern = '/^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+.[A-Za-z]{2,}$/';
if (preg_match($pattern, $email)) {
    echo 'Seems valid';
} else {
    echo 'Invalid';
}

این الگو یک بررسی پایه‌ای ایمیل انجام می‌دهد اما توجه داشته باشید که برای اعتبارسنجی دقیق ایمیل از filter_var($email, FILTER_VALIDATE_EMAIL) استفاده کنید؛ regex ممکن است همهٔ موارد استاندارد RFC را پوشش ندهد.

خلاصه و نکات پایانی

  • preg_match() ابزار قدرتمندی برای تشخیص و استخراج الگوهاست اما باید با احتیاط و دانش ساخته شود.
  • همیشه الگوها را تست کنید و برای داده‌های کاربر از preg_quote() بهره ببرید.
  • برای متن‌های یونیکد مد u را فراموش نکنید و در صورت نیاز به همهٔ تطابق‌ها از preg_match_all() استفاده کنید.

مطالعه مستندات رسمی PHP و تست الگوها با ابزارهای آنلاین (Regex101 با حالت PHP/PCRE) می‌تواند به درک بهتر و عیب‌یابی سریع کمک کند.

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

خیر
بله
موضوعات شما در انجمن: