Menu

Regex ב-Python: המודול re, תבניות, קבוצות והחלפה

היכרות מעשית עם המודול re של Python: חיפוש, התאמה, קבוצות לכידה, החלפה והתבניות שתשתמשו בהן הכי הרבה.

בדף הזה יש עורכים שאפשר להריץ - לערוך, להריץ ולראות את הפלט מיד.

מתי להשתמש ב-Regex

ביטויים רגולריים הם שפה קטנה לתיאור תבניות טקסט. הם חזקים, וקל להשתמש בהם יותר מדי.

לפני שפונים ל-re, שאלו אם מתודות מחרוזת רגילות יספיקו. .split(), .replace(), .startswith(), "target" in text: הן מהירות יותר, קריאות יותר ופחות מועדות לשגיאות מה-regex המקביל. שמרו את ה-regex למקרים שבהם התבנית שחשובה לכם באמת מובנית, אבל גמישה מדי לפעולות מחרוזת קבועות: כתובות אימייל, מספרי טלפון, שורות לוג עם צורה ידועה, קטעי HTML או Markdown, כל חיפוש של "מצא דבר מהסוג הזה".

אוצר המילים הבסיסי

תבנית regex היא מחרוזת שמתארת את מה שאתם מחפשים. כמה אבני בניין:

  • .: כל תו בודד
  • \d: כל ספרה (0 עד 9)
  • \w: כל תו "מילה" (אות, ספרה, קו תחתון)
  • \s: כל תו רווח לבן
  • ^: תחילת המחרוזת
  • $: סוף המחרוזת
  • [abc]: אחד מ-a, b או c
  • [^abc]: כל תו חוץ מ-a, b, c
  • a|b: a או b
  • *: אפס או יותר מהדבר הקודם
  • +: אחד או יותר
  • ?: אפס או אחד
  • {3}: בדיוק 3
  • {2,5}: בין 2 ל-5
  • ( ... ): קבוצה (לוכדת את ההתאמה שבפנים)

זה מספיק לרוב הביטויים הרגולריים בעולם האמיתי.

הפונקציות המרכזיות

re.search(pattern, text) מוצאת את ההתאמה הראשונה בכל מקום במחרוזת. היא מחזירה אובייקט התאמה או None:

תמיד השתמשו ב-raw string (r"...") לתבניות regex. אחרת Python מנסה לפרש את הלוכסנים ההפוכים כרצפי escape של מחרוזת, ומקבלים תבנית שונה ממה שהקלדתם.

re.match(pattern, text) דומה ל-search, אבל מתאימה רק בהתחלה:

ברוב המקרים רוצים את search.

re.findall(pattern, text) מחזירה את כל ההתאמות שאינן חופפות, כרשימה:

שימו לב ש-findall מחזירה מחרוזות, לא אובייקטי התאמה. אם בתבנית יש קבוצה אחת, מקבלים בחזרה את תוכן הקבוצה. עם כמה קבוצות, מקבלים רשימה של tuples.

קבוצות לכידה

סוגריים בתבנית לוכדים את מה שהותאם בתוכם:

קבוצות עם שם בדרך כלל ברורות יותר:

ברגע שיש ב-regex יותר מקבוצה אחת, מתן שמות לקבוצות הופך את קוד החילוץ לקל הרבה יותר למעקב.

החלפה עם re.sub

re.sub(pattern, replacement, text) מחליפה כל התאמה:

זה מסיר כל מה שאינו ספרה. ההחלפה יכולה להפנות לקבוצות שנלכדו עם \1, \2 וכן הלאה, או ב-raw strings, \g<1> ברור יותר:

אפשר גם להעביר פונקציה כהחלפה. זה שימושי להמרות שאינן החלפה פשוטה:

הידור תבניות לשימוש חוזר

אם אתם משתמשים באותה תבנית פעמים רבות, במיוחד בלולאה, הדרו (compile) אותה פעם אחת:

תבניות מהודרות חושפות את אותן מתודות, search, match, findall, sub, בלי התבנית כארגומנט הראשון. מעט יעילות יותר, ולעיתים קרובות קריאות יותר.

דגלים (Flags)

משנים נפוצים, שמועברים כארגומנט flags= או משולבים יחד עם OR:

  • re.IGNORECASE (re.I): התאמה שאינה רגישה לאותיות גדולות וקטנות.
  • re.MULTILINE (re.M): ^ ו-$ מתאימים בכל שורה, לא רק בגבולות המחרוזת.
  • re.DOTALL (re.S): . מתאים גם לתווי שורה חדשה (כברירת מחדל הוא לא).
  • re.VERBOSE (re.X): מאפשר רווחים והערות # בתוך התבנית, לשיפור הקריאוּת.

re.VERBOSE שימושי במיוחד לתבניות מורכבות:

ביטויים רגולריים בכמה שורות ועם הערות קלים לתחזוקה הרבה יותר משורות אחת אטומות.

Greedy לעומת Lazy

כמתים (*, +, ?, {n,}) הם חמדנים (greedy) כברירת מחדל: הם מתאימים כמה שיותר. הוסיפו ? כדי להפוך אותם ל_עצלים_ (lazy):

הגרסה החמדנית לוכדת את כל תת-המחרוזת מ-<b> ועד </i>, וכנראה שזה לא מה שרציתם. ה-.+? העצל עוצר ב-> הראשון.

(הערת אגב: אל תפענחו HTML עם regex בסביבת ייצור. השתמשו ב-html.parser או ב-BeautifulSoup. הדוגמה שלמעלה נועדה רק להמחיש חמדנות.)

דוגמה מציאותית

פענוח שורות מפורמט לוג פשוט:

הרבה כוח בלא הרבה שורות.

כמה הרגלים

  • תמיד השתמשו ב-raw strings לתבניות.
  • התחילו בתבנית הפשוטה ביותר שעובדת, והדקו אותה אחר כך.
  • השתמשו בקבוצות עם שם ברגע שיש יותר מקבוצה אחת.
  • הדרו תבניות שתשתמשו בהן שוב.
  • regex איטי יותר ממתודות מחרוזת רגילות. אם .split() מספיקה, השתמשו ב-.split().

הצעד הבא: שגיאות ודיבאגינג

בזה מסתיים הסיור בנתונים אמיתיים: קבצים, JSON, CSV, HTTP, תאריכים ו-regex. אבל כל תוכנית אמיתית נתקלת במוקדם או במאוחר בשגיאה, וקריאה טובה של tracebacks של Python היא מיומנות הדיבאגינג החשובה ביותר שאפשר לרכוש. הפרק האחרון מסביר חריגות ואת השגיאות הספציפיות שתיתקלו בהן הכי הרבה.

שאלות נפוצות

מה זה regex ב-Python?

ביטוי רגולרי (regex) הוא שפה קטנה לתיאור תבניות בטקסט. המודול re של Python מאפשר לחפש תבניות, לחלץ חלקים ולהחליף התאמות. הוא מוגזם לפעולות מחרוזת פשוטות, ועדיף להתחיל במתודות מחרוזת כמו .split() או .replace(), אבל אין לו מתחרים בהתאמת תבניות מובנות.

מה ההבדל בין re.match ל-re.search?

re.match מתאימה רק בתחילת המחרוזת. re.search סורקת את כל המחרוזת ומוצאת את ההתאמה הראשונה בכל מקום. כשיש ספק, השתמשו ב-search: היא מתאימה יותר לאינטואיציה האנושית.

האם תמיד להשתמש ב-raw strings לתבניות regex?

כן. תבניות regex מכילות לעיתים קרובות לוכסנים הפוכים (\d, \s, \b), ש-Python מפרשת במחרוזות רגילות כרצפי escape. הקידומת r, כמו ב-r'\d+', אומרת ל-Python לקחת את המחרוזת כפשוטה, וכך ה-regex עצמו נשאר קריא.

איור של שפות התכנות ב-Coddy

ללמוד תכנות עם Coddy

להתחיל