JavaRush /בלוג Java /Random-HE /RegEx: 20 צעדים קצרים לשליטה בביטויים רגולריים. חלק 2
Artur
רָמָה
Tallinn

RegEx: 20 צעדים קצרים לשליטה בביטויים רגולריים. חלק 2

פורסם בקבוצה
RegEx: 20 צעדים קצרים לשליטה בביטויים רגולריים. חלק 1 מקורי כאן בחלק האחרון שלטנו בביטויים הרגולריים הפשוטים ביותר, וכבר למדנו משהו. בחלק זה נלמד עיצובים קצת יותר מורכבים, אבל תאמינו לי, זה לא יהיה קשה כמו שזה אולי נראה. RegEx: 20 צעדים קצרים לשליטה בביטויים רגולריים.  חלק 2 - 1אז בואו נמשיך!

שלב 8: כוכב *וסימן פלוס+

RegEx: 20 צעדים קצרים לשליטה בביטויים רגולריים.  חלק 2 - 2עד כה, פחות או יותר הצלחנו להתאים רק מחרוזות באורך נתון. אבל בבעיות האחרונות התקרבנו לגבול של מה שאנחנו יכולים לעשות עם הסימון שראינו עד כה. נניח, למשל, שאנחנו לא מוגבלים למזהי Java בני 3 תווים, אלא שיכולים להיות לנו מזהים בכל אורך. פתרון שאולי עבד בדוגמה הקודמת לא יעבוד בדוגמה הבאה:
תבנית: [a-zA-Z_$]\w\w 
מחרוזת:   __e $12 3 3.2 fo Bar r a23 mm ab x
תואם: ^^^ ^^^ ^^^ ^^^  
( דוגמא ) הערהשכאשר מזהה חוקי אך ארוך מ-3 תווים, רק שלושת התווים הראשונים מתאימים. וכאשר המזהה תקף, אבל מכיל פחות מ-3 תווים, אז רגקס לא מוצא אותו בכלל! הבעיה היא שביטויים בסוגריים []תואמים בדיוק תו אחד, וכך גם מחלקות תווים כגון \w. המשמעות היא שכל התאמות בביטוי הרגולרי שלעיל חייבות להיות באורך של שלושה תווים בדיוק. אז זה לא עובד כמו שאולי קיווינו. *הדמויות המיוחדות ויכולות לעזור כאן +. אלה הם מתקנים שניתן להוסיף מימין לכל ביטוי כדי להתאים לאותו ביטוי יותר מפעם אחת. כוכב Kleene (או "כוכבית") *יציין שיש להתאים את האסימון הקודם לכל מספר פעמים, כולל אפס פעמים. סימן הפלוס +יציין שעליך לחפש פעם אחת או יותר. לפיכך, הביטוי שלפניו +הוא חובה (לפחות פעם אחת), בעוד שהביטוי שלפניו *הוא אופציונלי, אך כאשר הוא מופיע, הוא יכול להופיע בכל מספר פעמים. כעת, עם הידע הזה, אנו יכולים לתקן את הביטוי הרגולרי לעיל:
תבנית: [a-zA-Z_$]\w* 
מחרוזת:   __e $123 3.2 fo Barr a23mm ab x 
תואם: ^^^ ^^^^ ^^ ^^^^ ^^^^^ ^^ ^ 
( דוגמה ) כעת אנו מתאימים מזהים חוקיים בכל אורך! בינגו! אבל מה יקרה אם היינו משתמשים ב- +במקום *?
תבנית: [a-zA-Z_$]\w+ 
מחרוזת:   __e $123 3.2 fo Barr a23mm ab x
תואם: ^^^ ^^^^ ^^ ^^^^ ^^^^^ ^^ 
( דוגמה ) החמצנו את המשחק האחרון, х. הסיבה לכך היא שהוא דורש +התאמה של תו אחד לפחות, אך מכיוון שהביטוי בסוגריים []שלפניו \w+כבר 'אכל' את התו x, אין יותר תווים זמינים, כך שההתאמה נכשלת. מתי נוכל להשתמש +? כאשר אנחנו צריכים למצוא לפחות התאמה אחת, אבל זה לא משנה כמה פעמים ביטוי נתון חייב להתאים. לדוגמה, אם ברצוננו למצוא מספרים המכילים נקודה עשרונית:
תבנית: \d*\.\d+ 
מחרוזת:   0.011 .2 42 2.0 3.33 4.000 5 6 7.89012 
התאמות: ^^^^^ ^^ ^^^ ^^^^ ^^^^^^^^^^^^^  
( דוגמא ) הערהשעל ידי הפיכת המספרים משמאל לנקודה העשרונית לאופציונליים, הצלחנו למצוא גם 0.011 וגם .2. לשם כך, היינו צריכים להתאים בדיוק נקודה עשרונית אחת עם \.ולפחות ספרה אחת מימין לנקודה העשרונית עם \d+. הביטוי הרגולרי שלמעלה לא יתאים למספר כמו 3., כי אנחנו צריכים לפחות ספרה אחת מימין לנקודה העשרונית כדי להתאים.

כרגיל, בואו נפתור כמה בעיות פשוטות:

מצא את כל המילים באנגלית בקטע למטה.
תבנית:
מחרוזת: 3 ועוד 3 זה שש אבל 4 ועוד שלוש זה 7
תואם:    ^^^^ ^^ ^^^ ^^^ ^^^^ ^^^^^ ^^ 
( פתרון ) מצא את כל סמלי גודל הקובץ ברשימה למטה. גדלי הקבצים יהיו מורכבים ממספר (עם או בלי נקודה עשרונית) ואחריו KB, MB, GBאו TB:
תבנית:
מחרוזת:   11TB 13 14.4MB 22HB 9.9GB TB 0KB 
תואמים: ^^^^ ^^^^^^ ^^^^^ ^^^  
( פתרון )

שלב 9: סימן שאלה "אופציונלי".?

RegEx: 20 צעדים קצרים לשליטה בביטויים רגולריים.  חלק 2 - 3האם כבר כתבת regex כדי לפתור את הבעיה האחרונה? האם זה עבד? עכשיו נסה ליישם את זה כאן:
תבנית:
מחרוזת: 1..3KB 5...GB ..6TB
התאמות:  
ברור שאף אחד מהייעודים הללו אינו גודל קובץ חוקי, כך שביטוי רגולרי טוב לא אמור להתאים לאף אחד מהם. הפתרון שכתבתי כדי לפתור את הבעיה האחרונה תואם את כולם, לפחות בחלקו:
תבנית: \d+\.*\d*[KMGT]B 
מחרוזת:   1..3KB  5...GB .. 6TB 
תואמים: ^^^^^^ ^^^^^^ ^^^ 
( דוגמה ) אז מה הבעיה? למעשה, אנחנו צריכים למצוא רק נקודה עשרונית אחת, אם יש כזו. אבל *זה מאפשר כל מספר של התאמות, כולל אפס. האם יש דרך להתאים רק אפס פעמים או פעם אחת? אבל לא יותר מפעם אחת? כמובן שיש. "אופציונלי" ?הוא משנה שתואם לאפס או אחד מהתווים הקודמים, אך לא יותר:
תבנית: \d+\.?\d*[KMGT]B 
מחרוזת: 1.. 3KB 5...GB .. 6TB 
תואמים:     ^^^ ^^^ 
( דוגמה ) אנחנו קרובים יותר לפתרון כאן, אבל זה לא בדיוק מה שאנחנו צריכים. נראה כיצד לתקן זאת בכמה שלבים מעט מאוחר יותר.

בינתיים, בואו נפתור את הבעיה הזו:

בשפות תכנות מסוימות (למשל Java), מספרים שלמים ונקודה צפה (נקודה) עשויים להיות בעקבות l/ Lו f/ Fכדי לציין שיש להתייחס אליהם כאל ארוכים/צפים (בהתאמה) ולא כאל int/כפול רגילים. מצא את כל המספרים ה"ארוכים" החוקיים בשורה למטה:
תבנית:
מחרוזת:   13 ליטר ארוך 2 ליטר 19 ליטר lL 0 
תואמים: ^^^ ^^ ^^ ^ 
( פתרון )

שלב 10: סימן "או".|

RegEx: 20 צעדים קצרים לשליטה בביטויים רגולריים.  חלק 2 - 4בשלב 8, היה לנו קצת קושי למצוא את הסוגים השונים של מספרי נקודה צפה:
תבנית: \d*\.\d+ 
מחרוזת:   0.011 .2 42 2.0 3.33 4.000 5 6 7.89012 
התאמות: ^^^^^ ^^ ^^^ ^^^^ ^^^^^^^^^^^^^  
התבנית שלעיל תואמת מספרים עם נקודה עשרונית ולפחות ספרה אחת מימין לנקודה העשרונית. אבל מה אם נרצה גם להתאים מחרוזות כמו 0.? (ללא מספרים מימין לנקודה העשרונית.) נוכל לכתוב ביטוי רגולרי כך:
דפוס: \d*\.\d* 
מחרוזת:   0.011 .2 42 2.0 3.33 4,000 5 6 7.89012 0. . 
תואם: ^^^^^ ^^ ^^^ ^^^^ ^^^^^ ^^^^^^^ ^^ ^ 
( דוגמה ) זה תואם 0., אבל זה תואם גם נקודה בודדת ., כפי שניתן לראות למעלה. למעשה, מה שאנחנו מנסים להתאים הם שתי מחלקות מחרוזות שונות:
  1. מספרים עם ספרה אחת לפחות מימין לנקודה העשרונית
  2. מספרים עם ספרה אחת לפחות משמאל לנקודה העשרונית
בוא נכתוב את 2 הביטויים הרגולריים הבאים, בלתי תלויים זה בזה:
דפוס: \d*\.\d+ 
מחרוזת:   0.011 .2 42 2.0 3.33 4,000 5 6 7.89012 0. .
תואם: ^^^^^ ^^ ^^^ ^^^^ ^^^^^ ^^^^^^^  
דפוס: \d+\.\d* 
מחרוזת:   0.011 .2 42 2.0 3.33 4.000 5 6 7.89012 0. .
תואם: ^^^^^ ^^^ ^^^^ ^^^^^ ^^^^^^^ ^^ 
אנו רואים שבאף אחד מהמקרים הללו המחרוזות המשנה 42, 5, 6או .לא נמצאות על ידי המנוע. כדי להשיג את התוצאה הנדרשת, לא יזיק לנו לשלב את הביטויים הרגולריים הללו. איך נוכל להשיג זאת? הסימן "או" |מאפשר לנו לציין כמה רצפים אפשריים של התאמות בבת אחת בביטוי רגולרי. בדיוק כפי []שהסימן "או" מאפשר לנו לציין תווים בודדים חלופיים, |אנו יכולים לציין ביטויים חלופיים מרובי תווים. לדוגמה, אם נרצה למצוא "כלב" או "חתול", נוכל לכתוב משהו כזה:
דפוס: \ w\w\w 
string:   ברור שכלב הוא חיית מחמד טובה יותר מאשר חתול .
תואם: ^^^^^^^^^^ ^^^ ^^^^^^ ^^^ ^^^ ^^^ 
( דוגמה ) ... אבל זה מתאים לכל רצפי התווים המשולשים של המחלקה "מילה". אבל ל"כלב" ול"חתול" אין אפילו אותיות משותפות, אז סוגריים מרובעים לא יעזרו לנו כאן. להלן הביטוי הרגולרי הפשוט ביותר שנוכל להשתמש בו המתאים לשתי המילים ולשתי המילים הללו בלבד:
דפוס: dog|cat 
string: ברור שכלב הוא חיית מחמד טובה יותר מחתול .
תואם:               ^^^ ^^^ 
( דוגמה ) מנוע הביטוי הרגולרי מנסה תחילה להתאים את הרצף כולו משמאל לתו |, אך אם הוא נכשל, הוא מנסה להתאים את הרצף מימין לתו |. |ניתן גם לשרשר מספר תווים כדי להתאים ליותר משני רצפים חלופיים:
דפוס: dog| cat | 
מחרוזת חיות מחמד: ברור שכלב הוא חיית מחמד טובה יותר מחתול .
תואם:               ^^^ ^^^ ^^^ 
( דוגמא )

עכשיו בואו נפתור עוד כמה בעיות כדי להבין טוב יותר את השלב הזה:

השתמש בסימן |כדי לתקן את הביטוי הרגולרי העשרוני למעלה כדי להפיק תוצאה כזו:
תבנית:
מחרוזת:   0.011 .2 42 2.0 3.33 4.000 5 6 7.89012 0. .
תואם: ^^^^^ ^^ ^^^ ^^^^ ^^^^^ ^^^^^^^ ^^ 
( פתרון ) השתמש בסימן |, מחלקות תווים, "אופציונלי" ?וכו' כדי ליצור ביטוי רגולרי יחיד התואם הן מספר שלם והן מספרי נקודה צפה (נקודה), כפי שנדון בבעיה בסוף השלב הקודם (בעיה זו קצת יותר מסובך, כן ;))
תבנית:
מחרוזת:   42L 12 x 3.4f 6l 3.3 0F LF .2F 0. 
תואמים: ^^^ ^^ ^^^^ ^^ ^^^ ^^ ^^^ ^^  
( פתרון ) 20 צעדים קצרים לשליטה בביטויים רגולריים. חלק 3 RegEx: 20 צעדים קצרים לשליטה בביטויים רגולריים. חלק 4
הערות
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION