ביטויים רגילים בקוטלין

1. הקדמה

אנו יכולים למצוא שימוש (או שימוש לרעה) בביטויים רגולריים כמעט בכל סוג של תוכנה, החל מתסריטים מהירים וכלה ביישומים מורכבים להפליא.

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

לא נדון בתחביר של ביטוי רגולרי; בדרך כלל נדרשת היכרות עם ביטויים רגולריים כדי לעקוב אחר המאמר בצורה נאותה, ומומלץ לדעת על התחביר של תבנית Java.

2. התקנה

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

כנראה שכבר יש לנו את זה כתלות בפרויקט שלנו:

 org.jetbrains.kotlin kotlin-stdlib 1.2.21 

אנו יכולים למצוא את הגרסה האחרונה של kotlin-stdlib ב- Maven Central.

3. יצירת אובייקט ביטוי רגולרי

ביטויים רגולריים הם מקרים של kotlin.text.Regex מעמד. אנו יכולים ליצור אחת בכמה דרכים.

אפשרות היא להתקשר ל רגקס בַּנַאִי:

Regex ("a [bc] + d?")

או שאנחנו יכולים להתקשר ל toRegex שיטה על א חוּט:

"a [bc] + d?". toRegex ()

לבסוף, אנו יכולים להשתמש בשיטת מפעל סטטית:

Regex.fromLiteral ("a [bc] + d?")

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

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

"" "a [bc] + d? \ W" "". toRegex ()

3.1. אפשרויות התאמה

שניהם רגקס בנאי וה toRegex השיטה מאפשרת לנו לציין אפשרות אחת נוספת או קבוצה:

Regex ("a (b | c) + d?", CANON_EQ) Regex ("a (b | c) + d?", SetOf (DOT_MATCHES_ALL, COMMENTS)) "a (b | c) + d?". ToRegex (MULTILINE) "a (b | c) + d?". ToRegex (setOf (IGNORE_CASE, COMMENTS, UNIX_LINES))

האפשרויות מפורטות בסעיף אפשרות RegexOption class, שייבאנו בצורה נוחה באופן סטטי בדוגמה שלמעלה:

  • IGNORE_CASE - מאפשר התאמה ללא רגישות למקרה
  • רב-קו - משנה את המשמעות של ^ ו $ (לִרְאוֹת תבנית)
  • ליטרלי - גורם למטא-תווים או לרצפי בריחה בתבנית לא לקבל שום משמעות מיוחדת
  • UNIX_LINES במצב זה, רק ה \ n מוכר כמסיים קו
  • הערות - מאפשר מרחב לבן והערות בתבנית
  • DOT_MATCHES_ALL - גורם לנקודה להתאים לכל תו, כולל מסיים קו
  • CANON_EQ - מאפשר שוויון באמצעות פירוק קנוני (ראה תבנית)

4. התאמה

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

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

4.1. בדיקת התאמות חלקיות או סה"כ

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

אם נצטרך התאמה חלקית בלבד, נוכל להשתמש בה containMatchIn:

val regex = "" "a ([bc] +) d?" "". toRegex () assertTrue (regex.containsMatchIn ("xabcdy"))

אם אנחנו רוצים את השלם חוּט כדי להתאים במקום, אנו משתמשים התאמות:

assertTrue (regex.matches ("abcd"))

שים לב שנוכל להשתמש התאמות כמפעיל אינפיקס גם כן:

assertFalse (regex תואם "xabcdy")

4.2. חילוץ רכיבים תואמים

במקרי שימוש אלה, אנו רוצים כדי להתאים א חוּט נגד ביטוי קבוע ולחלץ חלקים מה- חוּט.

אולי נרצה להתאים את כל זה חוּט:

val matchResult = regex.matchEntire ("abbccbbd")

או אולי נרצה למצוא את המצע הראשון שמתאים:

val matchResult = regex.find ("abcbabbd")

או אולי למצוא את כל המצעים התואמים בבת אחת, כ- מַעֲרֶכֶת:

val matchResults = regex.findAll ("abcb abbd")

בשני המקרים, אם המשחק מוצלח, התוצאה תהיה אחד או יותר מהמקרים של MatchResult מעמד. בחלק הבא נראה כיצד להשתמש בו.

אם ההתאמה אינה מוצלחת, במקום זאת, שיטות אלה חוזרות ריק או הריק מַעֲרֶכֶת במקרה מצא הכל.

4.3. ה MatchResult מעמד

מקרים של MatchResult מחלקה מייצגת התאמות מוצלחות של מחרוזת קלט כלשהי כנגד ביטוי רגולרי; התאמות מלאות או חלקיות (ראו הסעיף הקודם).

ככאלה, יש להם ערך, שהוא התאמה חוּט או תשתית:

val regex = "" "a ([bc] +) d?" "". toRegex () val matchResult = regex.find ("abcb abbd") assertEquals ("abcb", matchResult.value)

ויש להם א טווח של המדדים כדי לציין איזה חלק מהקלט תואם:

assertEquals (IntRange (0, 3), matchResult.range)

4.4. קבוצות והרס

אנחנו יכולים גם לחלץ קבוצות (תשתית תואמת) מ MatchResult מקרים.

אנחנו יכולים להשיג אותם כ מיתרים:

assertEquals (listOf ("abcb", "bcb"), matchResult.groupValues)

או שאנחנו יכולים גם לראות אותם כ MatchGroup חפצים המורכבים מ- ערך ו טווח:

assertEquals (IntRange (1, 3), matchResult.groups [1] .range)

הקבוצה עם אינדקס 0 היא תמיד כל התאמה חוּט. מדדים הגדולים מ- 0, במקום זאת, מייצגים קבוצות בביטוי הרגולרי, המופרדות בסוגריים כגון ([bc] +) בדוגמה שלנו.

אנחנו יכולים גם להשמיד MatchResult מקרים בהצהרת מטלה:

val regex = "" "([\ w \ s] +) בן (\ d +) שנים" "". toRegex () val matchResult = regex.find ("מיקי מאוס בן 95") val (שם, גיל ) = matchResult !!. assertEquals הרס ("מיקי מאוס", שם) assertEquals ("95", גיל)

4.5. התאמות מרובות

MatchResult יש לו גם הַבָּא שיטה בה אנו יכולים להשתמש כדי להשיג את ההתאמה הבאה של הקלט חוּט נגד הביטוי הקבוע, אם יש:

val regex = "" "a ([bc] +) d?" "". toRegex () var matchResult = regex.find ("abcb abbd") assertEquals ("abcb", matchResult !!. value) matchResult = matchResult. הבא () assertEquals ("abbd", matchResult !!. value) matchResult = matchResult.next () assertNull (matchResult)

כמו שאנו יכולים לראות, הַבָּא מחזיר null כשאין יותר התאמות.

5. החלפה

שימוש נפוץ נוסף בביטויים רגולריים הוא החלפת מצעים תואמים לאחרים מיתרים.

לצורך כך יש לנו שתי שיטות זמינות בספריה הסטנדרטית.

אחד, החלף, מיועד להחלפת כל המופעים של התאמה חוּט:

val regex = "" "(אדום | ירוק | כחול)" "". toRegex () val יפה = "ורדים הם אדומים, סגולות כחולות" val grim = regex.replace (יפה, "כהה") טוענים שוויון ("ורדים הם כהה, סגולות כהות ", קודרות)

האחר, החלף ראשון, מיועד להחלפת ההתרחשות הראשונה בלבד:

val מבריק = regex.replaceFirst (יפה, "קשת") טוענים שווים ("ורדים הם קשת, סגולות כחולות", מבריק)

5.1. החלפות מורכבות

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

להיכנס ל החלף עומס יתר לוקח סגירה:

val reallyBeautiful = regex.replace (יפה) {m -> m.value.toUpperCase () + "!" } assertEquals ("ורדים אדומים! סגולות כחולות!", ממש יפה)

כפי שאנו רואים, עבור כל משחק אנו יכולים לחשב מחליף חוּט באמצעות התאמה זו.

6. פיצול

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

val regex = "" "\ W +" "". toRegex () val beautiful = "ורדים אדומים, סגולים כחולים" assertEquals (listOf ("ורדים", "הם", "אדום", "סגולים", "הם" , "כחול"), regex.split (יפה))

כאן הביטוי הרגולרי תואם לתו אחד או יותר שאינו מילה, כך שהתוצאה של פעולת הפיצול היא רשימת מילים.

אנו יכולים גם להגביל את אורך הרשימה המתקבלת:

assertEquals (listOf ("ורדים", "הם", "אדום", "סגולות כחולות"), regex.split (יפה, 4))

7. יכולת פעולה הדדית של Java

אם עלינו להעביר את הביטוי הרגיל שלנו לקוד ג'אווה, או לממשק API אחר בשפת JVM המצפה למופע של java.util.regex.Patternאנחנו יכולים פשוט להמיר את שלנו רגקס:

regex.toPattern ()

8. מסקנות

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

למידע נוסף ראו התייחסות לקוטלין.

ניתן למצוא את היישום של כל הדוגמאות וקטעי הקוד בפרויקט GitHub - זהו פרויקט של Maven, כך שיהיה קל לייבא ולהפעיל אותו כפי שהוא.


$config[zx-auto] not found$config[zx-overlay] not found