preg_match($pattern, $subject, $matches) בודקת אם מחרוזת מתאימה לביטוי רגולרי. היא מחזירה 1 כשיש התאמה ו-0 אחרת, וממלאת את $matches במה שמצאה: preg_match('/\d+/', 'Order 4521 shipped', $m) מחזירה 1 ומציבה ב-$m[0] את "4521".
התבנית היא מחרוזת עם מפרידים סביבה, בדרך כלל /.../, ואחריה משנים כמו i. כתבו תבניות בגרשיים בודדים: בתוך מירכאות כפולות PHP מפרקת קודם את $name ורצפי escape כמו \x41 או \101, ולכן מנוע ה-regex יכול לקבל תבנית שונה מזו שהקלדתם.
קבוצות לכידה
סוגריים בתבנית לוכדים את החלק של המחרוזת שהם מתאימים לו. $m[0] הוא ההתאמה כולה, $m[1] הקבוצה הראשונה, $m[2] השנייה, לפי סדר הסוגריים הפותחים.
קבוצות עם שם
(?<name>...) נותן לקבוצה שם. הערך נשמר תחת השם ותחת המספר שלה, כך שקוד שקורא את התוצאה לא נשבר כשמישהו מוסיף קבוצה מוקדם יותר בתבנית.
מציאת כל ההתאמות עם preg_match_all
preg_match_all() ממשיכה לחפש אחרי ההתאמה הראשונה ומחזירה את מספר ההתאמות. כברירת מחדל $m[0] מחזיק את כל ההתאמות המלאות ו-$m[1] את כל הערכים של הקבוצה הראשונה. עם PREG_SET_ORDER מקבלים במקום זאת מערך אחד לכל התאמה, ופשוט יותר לעבור עליו בלולאה.
אימות קלט: עוגנים, מספרי טלפון, מיקודים
לאימות, התבנית חייבת להתאים למחרוזת כולה, ולכן התחילו אותה ב-^ וסיימו אותה ב-$. מלכודת אחת: $ מתאים גם לפני ירידת שורה אחרונה, ולכן '/^\d+$/' מקבלת את "123\n". הוסיפו את המשנה D, או השתמשו ב-\z, שמתאים רק בסוף המוחלט.
בכתובות אימייל, regex או דוחה כתובות תקינות או מקבל כתובות לא תקינות. השתמשו במקום זאת ב-filter_var($email, FILTER_VALIDATE_EMAIL) (ראו filter_var()).
המשנה u לטקסט UTF-8 ויפני
בלי המשנה u, תבנית עובדת על בתים. תו יפני הוא שלושה בתים ב-UTF-8, ולכן . מתאים לשליש תו והאורכים יוצאים שגויים. עם u, התבנית עובדת על תווים ואפשר להשתמש במחלקות מאפיינים של Unicode.
u גם מאמת את המחרוזת: אם היא לא UTF-8 תקין, preg_match() מחזירה false במקום להתאים.
escape לקלט משתמש עם preg_quote
לתווים כמו ., +, ?, ( ו-/ יש משמעות מיוחדת בתבנית. אם חלק מהתבנית מגיע ממשתנה, כמו מונח חיפוש, העבירו אותו דרך preg_quote() עם המפריד כארגומנט השני, אחרת 1+1 יתאים ל-11 ו-/ בלי escape ישבור את התבנית.
תבנית לא תקינה לא זורקת חריגה. PHP מדפיסה אזהרה ו-preg_match() מחזירה false:
Warning: preg_match(): No ending delimiter '/' found in /path/to/index.php on line 3
לכן בדקו === false (או preg_last_error_msg()) כשהתבנית נבנית בזמן ריצה. לבדיקת תת מחרוזת פשוטה בלי שום תבנית, str_contains() מהירה וברורה יותר. כדי לשנות את הטקסט שהתאים, השתמשו ב-preg_replace().
שאלות נפוצות
מה preg_match מחזירה ב-PHP?
1 אם התבנית מתאימה, 0 אם לא, ו-false אם התבנית עצמה לא תקינה. כיוון ש-0 ו-false שניהם שקריים, השוו עם === 1 כשצריך להבדיל בין תבנית שנכשלה לבין חוסר התאמה.
איך מקבלים את הטקסט שהתאים מ-preg_match?
העבירו ארגומנט שלישי: preg_match('/(\d+)/', 'Order 4521', $m). אז $m[0] הוא ההתאמה כולה ו-$m[1] קבוצת הלכידה הראשונה, ושניהם "4521" כאן. עם קבוצה עם שם (?<id>\d+) הערך נמצא גם ב-$m['id'].
מה ההבדל בין preg_match ל-preg_match_all?
preg_match() עוצרת בהתאמה הראשונה. preg_match_all() מוצאת כל התאמה, מחזירה כמה מצאה, וממלאת את $matches בכולן: preg_match_all('/\d+/', 'a1 b22 c333', $m) מחזירה 3 ו-$m[0] הוא ["1", "22", "333"].
איך משתמשים ב-preg_match עם טקסט ביפנית או טקסט UTF-8 אחר?
הוסיפו את המשנה u: preg_match('/^.{3}$/u', '日本語') מחזירה 1. בלי u, PHP מתייחסת למחרוזת כבתים, ולכן . מתאים לבית אחד מתוך תו של 3 בתים. עם u אפשר גם להשתמש במחלקות Unicode כמו \p{Han}, \p{Hiragana} ו-\p{Katakana}.
איך בודקים אם מחרוזת מכילה רק מספרים ב-PHP?
preg_match('/^\d+$/D', $s) או, בלי regex, ctype_digit($s). המשנה D (או \z במקום $) חשוב: $ רגיל מקבל גם ירידת שורה בסוף, ולכן "123\n" היה עובר.