הצצה אחורה בביטוי רגולארי בפייתון
קבלו חידת ביטויים רגולריים פשוטה לפתוח את הבוקר: נתון הטקסט I am :the: walrus
ואנחנו רוצים לפצל אותו לשני חלקים כך שהחלק הראשון כולל את כל מה שמופיע עד הנקודותיים השניים (כולל הנקודותיים) והחלק השני כל מה שבא אחרי הרווחים.
כמו כן אם בהמשך יהיו עוד מקומות עם נקודותיים ואחריהם רווח נרצה לחזור על אותו פיצול.
טוב אז ברור ש split רגיל של מחרוזת לא יעבוד כאן - split יבלע לי את הנקודותיים ואת הרווח שאחריהן:
text = 'I am :the: walrus'
text.split(': ')
['I am :the', ' walrus']
אפשר לשפר את המצב במעבר לביטויים רגולאריים אבל זה עדיין לא מספיק טוב כי מקבלים שלושה חלקים במקום 2:
import re
text = 'I am :the: walrus'
re.split('(: )', text)
['I am :the', ': ', ' walrus']
וכן ראיתם נכון - בגלל ששמתי את הנקודותיים והווח בתוך סוגריים פייתון שמר אותם כאיבר נוסף ברשימת התוצאה. בלי הסוגריים התוצאה תהיה זהה ל str#split.
מנועי ביטויים רגולאריים תומכים במגוון סוגים של "הצצות". בניגוד לחיפוש רגיל, הצצה לא תופסת את החלק בקלט שמצאנו ומיועדת לסמן מיקום. בעברית נוכל להסביר שאני רוצה לפצל את השורה בתו רווח שלפניו יש נקודותיים. השם המקצועי של זה הוא Positive Lookbehind ובפייתון זה מסומן כך:
import re
text = 'I am :the: walrus'
re.split('(?<=:) ', text)
# or if you don't need the spaces before the walrus
re.split('(?<=:) +', text)
['I am :the:', 'walrus']
באופן כללי ובפרט בפייתון ארבעת סוגי ההצצות והסימנים שלהן הם:
הצצה קדימה - Positive Lookahead מסומן באמצעות
(?=foo)
. חיפוש המקום בקלט שאחריו מופיעה המילה foo.הצצה אחורה - Positive Lookbehind מסומן באמצעות
(?<=foo)
. חיפוש המקום בקלט שלפניו מופיעה המילה foo.הצצה קדימה שלילית -Negative Lookahead מסומן באמצעות
(?!foo)
. חיפוש מקום בקלט שאחריו לא מופיעה המילה foo.הצצה אחורה שלילית - Negative Lookbehind מסומן באמצעות
(?<!foo)
חיפוש המקום בקלט שלפניו לא מופיעה המילה foo.
לדוגמאות נוספות על Lookahead ו Lookbehind שווה להעיף מבט בקישור כאן:
href='http://www.rexegg.com/regex-lookaround
** בואו לכתוב איתי קוד: החודש אני מתחיל לקיים מפגשי תרגול בהם אנחנו כותבים יחד קוד ומדברים על הקוד שכתבנו. במפגשים תקבלו אינספור רעיונות חדשים איך לפתור בעיות. קראו עוד בעמוד מפגשי התרגול **