Regex - ביטויים רגולריים

פרק ראשון בסדרת Regex - ביטויים רגולריים

Authors
  • Name
    Dovid
    Published on
    Twitter

טקסט תמיד מורכב מאוסף של תווים, וביטוי רגולרי בא בהגדרתו למצוא רצף של כאלה תואם למה שביקשנו.

הביטוי עשוי לכלול אותיות רגילות לגמרי. למשל ביטוי כזה 'א' ימצא את כל אותיות הא' בטקסט בו מחפשים. כמו"כ הביטוי 'אני' יחפש את המילה אני או ליתר הדיוק את הרצף של האותיות א' נ' י'. עד כאן זה בעצם התנהגות של חיפוש רגיל ומוכר.

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

ג'וקרים

נתחיל מהפשוט: אנחנו רוצים למצוא תו כל שהוא (נקודה), תו כל שהוא אבל רק מתוך קבוצת תוים (סוגריים מרובעות [XYZ]), או תו כל שהוא למעט קבוצה מוחרגת (סוגריים מרובעות עם חץ למעלה בהתחלה [^XYZ]). נקרא לזה ג'וקרים, שימו לב, כל הג'וקרים מייצגים תו בודד בלבד! (כל התוים המיוחדים יוצרים בעיה, מה קורה כשרוצים לחפש תו פשוט שלרוע מזלו הינו מיוחד מבחינת הregex? צריך לבטל את ייחודיותו ע"י escaping נדבר על זה בהמשך).

. נקודה - תו אחד כלשהו
נקודה בביטוי רגולרי לא מייצגת את התו נקודה אלא היא סימן מיוחד, שמשמעותו "מתאים לי שתמצא איזה תו שתרצה". חיפוש של ביטוי רגולרי עם נקודה בלבד, יחזיר את כל התוים בטקסט (מס' התוצאות יהיה מס' התוים בטקסט הנתון), וזה לא הכי שימושי, אז נגיד דוגמה הגיונית יותר: חיפוש של 'א.' ימצא את כל אותיות הא' שבטקסט עם האות הסמוכה להם, תהיה אשר תהיה. כמו"כ חיפוש של 'א.י' יחזיר רצפים של א', תו כלשהוא, ואח"כ י', למשל אני, אלי, אוי (ואולי אפילו סיום של מילה בא' עם הרוח שאחריה ותו היוד של תחילת המילה הבאה).

[XXX] תו מקבוצה מוגדרת
תו אחד מקבוצה של תווים אפשריים. סוגריים מרובעות ובתוכם תווים, למשל [אהחער] מייצגת תו בודד ובלבד שהוא יהיה אחת מהאותיות (במקרה הזה, הגרוניות..) שבסוגריים. אם נחפש 'ב[אהחער]' זה יחפש אות ב' שאחריה ישנם אחת מהאותיות הללו, למשל בא, בה, בח.

[a-c] טווח
בסוגריים ניתן לכלול טווח תוים. טווח תוים זה אומר מתו עד תו, ללא צורך בהקלדתם בסוגריים. למשל במקום לכתוב [אבגד], ניתן לכתוב [א-ד]. מאיפה מנוע הרגקס יודע את סודות האלפא ביתא וסדרם? זה מתבסס על סדר התוים מבחינת המחשב. (וכמו השאלה בנקודה, אפשר לעשות גם טווחים וגם אותיות בודדות וגם כמה טווחים בסוגריים אחד, למשל [א-גלצ-ת] כולל את האותיות אבגלצקרשת (ומשמעותו 'מצא לי תו בודד שמופיע ברשימה זו').

[^XXX] שלילה
בעוד שראינו שהסוגריים המרובעות מייצגות תו מתוך קבוצה מוגדרת שמופיעה בסוגריים. לפעמים ההגדרה הקצרה ביותר היא הפוכה, תו מתוך כלל התוים בעולם ובלבד שלא יהיה מאלו המוגדרות בסוגריים! בשביל זה עושים סוגריים שמייד אחרי הפתיחה שלהם מופיע חץ למעלה ^. למשל, [^א-ג] ימצא כל תו למעט א, ב, וג'.

תוים מיוחדים
יש תוים שאי אפשר להקליד. למשל אם אתם מחפשים קפיצת שורה, או טאב, תכתבו תו מיוחד. למשל קפיצת שורה כותבים ע"י \n ואילו טאב \t יש עוד כמה כאלה. (רווח אפשר לכתוב כפי שהוא בביטוי החיפוש כמו כל אות רגילה).

קיצורים
למעשה עם הסוגריים מרובעות אפשר לבטא כל תו שרוצים או שלא, אבל יש חיפושים כ"כ נפוצים שהחליטו לעשות להם קיצור לשיפור השמישות וגם הקריאות. למשל. מספר כל שהוא, ניתן לקבל ע"י [0987654321] או בקיצור ע"י טווח [0-9]. אז קבעו לזה קיצור \d. כלומר לוכסן (הפוך, מהסוג של וינדוס לשימוש בנתיב קבצים) ואחריו אות הd באנגלית, משמשים קיצור ל[0-9] כלומר הם מייצגים תו בודד מ0 עד 9 שניתן להגדיר זאת כמספר כל שהוא. או למשל דוגמא נוספת: לפעמים מחפשים תוי רווח. תוי רווח זה שם כללי לסימנים ה"שקופים" שמפרידים בין מילים - חוץ מהרווח המוכר מהמקלדת, יש את הקפיצת שורה וטאב ועוד כמה. כולם כלולים בקיצור \s.

רשימת הקיצורים:
\d מספר כל שהוא, שקול ל[0-9]
\w תו של מילים, לאפוקי סימני פיסוק וגרוע מכך. קיצור של [a-zA-Z0-9_] (לא יודע למה כללו את הקו התחתי)
\s תו רווח כל שהוא, שקול ל[\r\n\t\f\v] (אל תשאלו אותי מה זה כל אחד...)

קיצורי שלילה
אם תרצו כל תו שאיננו מספר, אתם תרצו לכתוב משהו כמו [^0-9]. אבל הרי יש לנו \d שמשמעותו [0-9], אז תוכלו לכתוב [^\d]. אבל עליכם לדעת שגם לזה עשו קיצורים... קיצורי השלילה זהים לקיצורים הקודמים רק אות גדולה במקום קטנה, כלומר:

\D כל תו שאיננו מספר
\W כל תו שאיננו תו מילה - "נורמלי".
\S כל תו שאיננו רווח קפיצת שורה טאב וכל החבורה.

חזרה וכמות ({}, +, *, ?)

כמה פעמים האלמנט (צריך/יכול) להופיע?

זו קבוצת סימנים, שההגדרה שלה היא "האלמנט (ברוב המקרים התו, לפעמים זה קבוצת תוים עטופה סוגריים) שאמרנו לך לחפש, תמצא אותו ? פעמים". נשמע מסובך... ככה: אם אנו מחפשים מספר כל שהוא, אנחנו כותבים \d או באריכות [0-9]. אבל זה מביא לנו ספרה בודדת. אם נרצה מספר בעל אורך מסויים למשל מס' חשבונית שאנו יודעים שתמיד מכילה 9 ספרות, נצטרך לכתוב ככה \d\d\d\d\d\d\d\d\d ובגירסה הארוכה [0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]. יאהוו.
בשביל זה יש מצייני כמות.

{X} או {Y,X} או {,Y} מX עד Y. כלומר האלמנט האחרון שהתבקש, צריך להיות לפחות X פעמים והכי הרבה Y פעמים. למשל, א{2,3} (הסדר הוא קודם המינימום, פסיק מקסימום) יחזיר מקרים בהם יש שתי אותיות א רצופות או שלוש (מקבוצה של ארבע הוא ייקח/יימצא/יתאים רק את השלושה תוים ראשונים). אם אכפת לנו רק המינימום, ואין לנו הגבלה עד כמה, נשמיט את הפסיק והמספר השני. אם להיפך, אנו רוצים גם מספר אחד, אבל לא יעלה על 9, נשמיט את הראשון אך נשאיר אתהפסיק (נכתוב תו לחיפוש, סוגר מסולסל פותח ופסיק, מס' מקסימלי סגירת סוגר מסולסל. האריכות בגלל שיבושי הכיוונים בעברית 🙂). שימו לב, כל מצייני הכמות מתייחסים לאלמנט הצמוד שקדם להם. הסימנים הם ?+*{}

כוכבית * 0 או יותר. האלמנט האחרון יכול להופיע 0 פעמים (אז הוא גם אופציונלי בעצם) אבל עד אין סוף. חיפוש .* יחזיר פשוט את כל הטקסט כתוצאה אחת - שהרי פירוש הביטוי הוא תו כל שהוא כפול מספר לא ידוע של פעמים. עוד דוגמא א\d* יחזיר כל רצף מספרי שקדם לה האות א' (בהמשך נלמד שכל החיפשוים ברגקס הם חמדניים -לוקחים כמה שיותר. ממילא ממספר של 4 ספרות לא תיהיה התאמה רק של 3 גם אם זה נכון מבחינת כללי החיפוש, כל עוד יכולה להיות התאמה גדולה יותר- של 4).

סימן הפלוס + אחד או יותר. אותו דבר כמו כוכבית, אבל בניגוד אליה, היא מחייבת שהאלמנט יופיע לכל הפחות פעם אחת. בעוד א\d* ימצא גם א שאין אחריו מספר כלל, א\d+ ימצא רק א' שאחריו יש לפחות ספרה בודדת ואילך.

סימן שאלה ? אפס או אחד. זה בעצם אומר שהאלמנט האחרון הוא אופציונלי. אם נרצה לחפש בוקר, בכתיב מלא או חסר, נחפש בו?קר שמשמעותו ב, שאחרי זה תיתכן האות ו ותיתכן שלא ואחרי זה ק'ר'. או שליט"?א ימצא גם שליטא ללא ראשי תיבות. בר ?כל ימצא גם ברכל שהרי הרווח הוא אופציונלי. אם נחשוש שיהיו תוצאות כאלה בר-כל, בר_כל, ניטיב לכתוב בר.?כל. זה ימצא כל תו, וגם בלעדיו כלומר ברכל רצוף.

הערה, יש מושג כימות עצלן: כל מצייני הכמות מנסים תמיד למצוא את המקסימום. למשל אם נחפש אלמנט HTML שזה בעצם טקסט מוקף זויות, אנו עשויים לחפש "<.+>" - משמעות: סוגריים זויתיות שביניהם 1 או יותר של תו כל שהוא. כעת אם יש כמה זוגות של כאלה בטקסט במקום למצוא כל אחד לעצמו הוא יתפוס מהראשון עד האחרון ברציפות! הנה דוגמה. זה התנהגות הברירת מחדל שנקראת חמדנית. ההיפך של זה נקרא התנהגות עצלנית והיא מושגת ע"י הוספת סימן שאלה אחרי מציין הכמות - הכוכבית או הפלוס, הנה דוגמא עובדת. המשמעות היא להעדיף את ההתאמה המינימלית.

טוב, אני כבר חרגתי, ההמשך יבוא אי"ה ויהיה על קבוצות.