JavaRush /בלוג Java /Random-HE /ביטויים רגולריים ב-Java, חלק 1

ביטויים רגולריים ב-Java, חלק 1

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

שימוש ב-API של ביטוי רגיל בתוכניות Java כדי לזהות ולתאר דפוסים

התווים של Java וסוגי המחרוזת השונים מספקים תמיכה ברמה נמוכה בהתאמת דפוסים, אך השימוש בהם למטרה זו מוסיף בדרך כלל מורכבות קוד משמעותית. קוד פשוט וביצועי יותר מתקבל על ידי שימוש ב-Regex API ("Regional Expression API"). מדריך זה יעזור לך להתחיל עם ביטויים רגולריים ו-Regex API. תחילה נדון בשלושת המחלקות המעניינות ביותר בחבילה באופן כללי java.util.regex, ולאחר מכן נסתכל בתוך הכיתה Patternונחקור את המבנים המתוחכמים של התאמת הדפוסים שלה. תשומת הלב: אתה יכול להוריד את קוד המקור (שיוצר על ידי ג'ף פריזן עבור אתר JavaWorld) של אפליקציית ההדגמה ממאמר זה מכאן .

מהם ביטויים רגולריים?

ביטוי רגולרי (ביטוי רגולרי/regex/regexp) הוא מחרוזת שהיא דפוס שמתאר קבוצה מסוימת של מחרוזות. התבנית קובעת אילו שורות שייכות לסט. התבנית מורכבת מדמויות מילוליות ומטא-דמויות - דמויות בעלות משמעות מיוחדת ולא משמעות מילולית. התאמת דפוסים היא חיפוש של טקסט כדי למצוא התאמות, כלומר מחרוזות התואמות לתבנית ביטוי רגולרי. Java תומכת בהתאמת דפוסים דרך ה-API של Regex. API זה מורכב משלוש מחלקות: Pattern, Matcherו PatternSyntaxException, הממוקמות בחבילה java.util.regex:
  • אובייקטי מחלקה Pattern, הנקראים גם תבניות, הם ביטויים רגולריים מורכבים.
  • אובייקטי מחלקה Matcher, או מתאמים, הם מנגנוני פירוש דפוסים למציאת התאמות ברצפי תווים (אובייקטים שהמחלקות שלהם מיישמות ממשק java.lang.CharSequenceומשמשות כמקורות טקסט).
  • אובייקטי מחלקה PatternSyntaxExceptionמשמשים לתיאור דפוסי ביטוי רגולרי לא חוקיים.
Java מספקת גם תמיכה בהתאמת דפוסים באמצעות שיטות שונות של ה- java.lang.String. לדוגמה, הפונקציה boolean matches (String regex)מחזירה trueרק אם המחרוזת הקוראת תואמת בדיוק לביטוי הרגולרי regex.
שיטות נוחות
matches()ושיטות נוחות אחרות המוכוונות לביטוי רגולרי של המחלקה Stringמיושמות מתחת למכסה המנוע באופן דומה ל-Regex API.

RegexDemo

יצרתי אפליקציה RegexDemoלהדגמת ביטויים רגולריים של Java ושיטות שונות של ה- Pattern, Matcherו- PatternSyntaxException. להלן קוד המקור עבור יישום הדגמה זה. רישום 1. הדגמת ביטוי רגולרי
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
public class RegexDemo
{
   public static void main(String[] args)
   {
      if (args.length != 2)
      {
         System.err.println("usage: java RegexDemo regex input");
         return;
      }
      // Преобразуем символьные последовательности начала новой строки (\n) в символы начала строки.
      args[1] = args[1].replaceAll("\\\\n", "\n");
      try
      {
         System.out.println("regex = " + args[0]);
         System.out.println("input = " + args[1]);
         Pattern p = Pattern.compile(args[0]);
         Matcher m = p.matcher(args[1]);
         while (m.find())
            System.out.println("Found [" + m.group() + "] starting at "
                               + m.start() + " and ending at " + (m.end() - 1));
      }
      catch (PatternSyntaxException pse)
      {
         System.err.println("Неправильное регулярное выражение: " + pse.getMessage());
         System.err.println("Описание: " + pse.getDescription());
         System.err.println("Позиция: " + pse.getIndex());
         System.err.println("Неправильный шаблон: " + pse.getPattern());
      }
   }
}
mainהדבר הראשון ששיטת מחלקה עושה RegexDemoהוא לבדוק את שורת הפקודה שלה. זה דורש שני ארגומנטים: הראשון הוא ביטוי רגולרי, והשני הוא טקסט הקלט שבו יחפשו את הביטוי הרגולרי. ייתכן שיהיה עליך להשתמש בתו שורה חדשה בתוך טקסט הקלט (\n). ניתן לעשות זאת רק על ידי ציון התו \ואחריו התו n. הפונקציה main()ממירה את רצף התווים הזה לערך Unicode 10. ביטויים רגולריים ב-Java, חלק 1 - 2עיקר הקוד RegexDemoמוקף ב- try-catch. הבלוק tryמוציא תחילה את הביטוי הרגולרי הנתון ואת טקסט הקלט, ולאחר מכן יוצר אובייקט Patternהמאחסן את הביטוי הרגולרי המהודר (ביטויים רגולריים מקומפלים כדי לשפר את ביצועי התאמת הדפוסים). תואם מופק מהאובייקט Patternומשמש לחיפוש התאמות באופן איטרטיבי עד שכולן נמצאות. הבלוק catchקורא לכמה שיטות מחלקות PatternSyntaxExceptionכדי לאחזר מידע שימושי על החריג. מידע זה מופק ברצף לזרם הפלט. אין צורך לדעת עדיין את הפרטים של אופן פעולת הקוד: הם יתבהרו כאשר נלמד את ה-API בחלק השני של המאמר. עם זאת, עליך להרכיב רישום 1. קח את הקוד מרשימה 1, ולאחר מכן הקלד את הפקודה הבאה בשורת הפקודה להידור RegexDemo: javac RegexDemo.java

כיתת Pattern והמבנים שלה

המחלקה Pattern, הראשונה מבין שלוש המחלקות המרכיבות את ה-API של Regex, היא ייצוג הידור של ביטוי רגולרי. תיעוד ה-SDK של המחלקה Patternמתאר מגוון של מבני ביטוי רגולרי, אך אם אינך משתמש באופן פעיל בביטויים רגולריים, חלקים מהתיעוד הזה עשויים לבלבל. מה הם מכמתים ומה ההבדל בין מכמתים חמדנים, סרבנים ורכושניים? מהן מחלקות תווים, התאמת גבולות, הפניות לאחור וביטויי דגל מוטבעים? על שאלות אלו ואחרות אענה בסעיפים הבאים.

מחרוזות מילוליות

מבנה הביטוי הרגולרי הפשוט ביותר הוא מחרוזת מילולית. כדי שהתאמת דפוסים תצליח, חלק כלשהו מטקסט הקלט חייב להתאים לדפוס של אותו מבנה. שקול את הדוגמה הבאה: java RegexDemo apple applet בדוגמה זו, אנו מנסים למצוא התאמה לתבנית appleבטקסט הקלט applet. התוצאה הבאה מציגה את ההתאמה שנמצאה:
regex = apple
input = applet
Found [apple] starting at 0 and ending at 4
אנו רואים בפלט את הביטוי הרגולרי ואת טקסט הקלט, ולאחר מכן אינדיקציה לזיהוי מוצלח appleביישומון. בנוסף, עמדות ההתחלה והסיום של משחק זה ניתנות: 0ו 4, בהתאמה. מיקום ההתחלה מציין את המקום הראשון בטקסט שבו נמצאה התאמה, ומיקום הסיום מציין את הנקודה האחרונה של ההתאמה. עכשיו נניח שנתנו את שורת הפקודה הבאה: java RegexDemo apple crabapple הפעם נקבל את התוצאה הבאה, עם עמדות התחלה וסיום שונות:
regex = apple
input = crabapple
Found [apple] starting at 4 and ending at 8
אחרת, עם וכביטוי appletהרגולרי apple- טקסט הקלט, לא יימצאו התאמות. הביטוי הרגולרי כולו חייב להתאים, אך במקרה זה, טקסט הקלט אינו מכיל tאחרי apple. ביטויים רגולריים ב-Java, חלק 1 - 3

מטא-תווים

מבני ביטוי רגולרי מעניינים יותר משלבים תווים מילוליים עם תווים מטא. לדוגמה, בביטוי רגולרי a.b, המטא-תו נקודה (.)פירושו כל תו בין aלבין b. שקול את הדוגמה הבאה: java RegexDemo .ox "The quick brown fox jumps over the lazy ox." דוגמה זו משתמשת .oxהן כביטוי רגולרי והן The quick brown fox jumps over the lazy ox.כטקסט קלט. RegexDemoמחפש בטקסט התאמות שמתחילות בכל תו ומסתיימות בתוצאות ox.ביצועו הן כדלקמן:
regex = .ox
input = The quick brown fox jumps over the lazy ox.
Found [fox] starting at 16 and ending at 18
Found [ ox] starting at 39 and ending at 41
בפלט אנו רואים שתי התאמות: foxו ox(עם תו רווח לפניו). המטא תו . מתאים לדמות fבמקרה הראשון ולרווח במקרה השני. מה קורה אם מחליפים אותו .oxבתו מטא .? כלומר, מה שנקבל כתוצאה משורת הפקודה הבאה: java RegexDemo . "The quick brown fox jumps over the lazy ox." מכיוון ש-dot metacharacter תואם לכל תו, RegexDemoיפלוט התאמות שנמצאו עבור כל התווים (כולל תו הנקודה הנגררת) של טקסט הקלט:
regex = .
input = The quick brown fox jumps over the lazy ox.
Found [T] starting at 0 and ending at 0
Found [h] starting at 1 and ending at 1
Found [e] starting at 2 and ending at 2
Found [ ] starting at 3 and ending at 3
Found [q] starting at 4 and ending at 4
Found [u] starting at 5 and ending at 5
Found [i] starting at 6 and ending at 6
Found [c] starting at 7 and ending at 7
Found [k] starting at 8 and ending at 8
Found [ ] starting at 9 and ending at 9
Found [b] starting at 10 and ending at 10
Found [r] starting at 11 and ending at 11
Found [o] starting at 12 and ending at 12
Found [w] starting at 13 and ending at 13
Found [n] starting at 14 and ending at 14
Found [ ] starting at 15 and ending at 15
Found [f] starting at 16 and ending at 16
Found [o] starting at 17 and ending at 17
Found [x] starting at 18 and ending at 18
Found [ ] starting at 19 and ending at 19
Found [j] starting at 20 and ending at 20
Found [u] starting at 21 and ending at 21
Found [m] starting at 22 and ending at 22
Found [p] starting at 23 and ending at 23
Found [s] starting at 24 and ending at 24
Found [ ] starting at 25 and ending at 25
Found [o] starting at 26 and ending at 26
Found [v] starting at 27 and ending at 27
Found [e] starting at 28 and ending at 28
Found [r] starting at 29 and ending at 29
Found [ ] starting at 30 and ending at 30
Found [t] starting at 31 and ending at 31
Found [h] starting at 32 and ending at 32
Found [e] starting at 33 and ending at 33
Found [ ] starting at 34 and ending at 34
Found [l] starting at 35 and ending at 35
Found [a] starting at 36 and ending at 36
Found [z] starting at 37 and ending at 37
Found [y] starting at 38 and ending at 38
Found [ ] starting at 39 and ending at 39
Found [o] starting at 40 and ending at 40
Found [x] starting at 41 and ending at 41
Found [.] starting at 42 and ending at 42
ציטוט מטא-תווים
כדי לציין .או כל תו מטא אחר כתו מילולי במבנה ביטוי רגולרי, עליך להימלט ממנו באחת מהדרכים הבאות:
  • להקדים אותו עם תו נטוי אחורי;
  • מקם את המטא-תו זה בין \Qלבין \E(לדוגמה, \Q.\E).
זכור לשכפל את כל התווים המופיעים במחרוזת המילולית, כגון String regex = "\\.";קווים אחוריים (לדוגמה, \\.או \\Q.\\E). אל תשכפל את הנטוי האחורי המהווה חלק מארגומנט שורת פקודה.

שיעורי אופי

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

שיעורי תווים פשוטים

מחלקת תווים פשוטה מורכבת מתווים הממוקמים זה לצד זה ומתאימה רק לאותן תווים. לדוגמה, הכיתה [abc]תואמת את התווים a, bו c. שקול את הדוגמה הבאה: java RegexDemo [csw] cave כפי שניתן לראות מהתוצאות, בדוגמה זו רק התו cשעבורו יש התאמה ב cave:
regex = [csw]
input = cave
Found [c] starting at 0 and ending at 0

שיעורי אופי הפוכים

מחלקת תווים הפוכה מתחילה במטא-תו ^ומתאימה רק לאותם תווים שאינם כלולים בה. לדוגמה, המחלקה [^abc]מתאימה לכל התווים מלבד a, bו c. קחו בחשבון את הדוגמה הבאה: java RegexDemo "[^csw]" cave שימו לב שבמערכת ההפעלה שלי (Windows) נדרשות מרכאות כפולות מכיוון שהמעטפת מתייחסת אליהן ^כאל תו בריחה. כפי שאתה יכול לראות, בדוגמה זו רק התווים a, vו- נמצאו e, עבורם יש התאמות ב cave:
regex = [^csw]
input = cave
Found [a] starting at 1 and ending at 1
Found [v] starting at 2 and ending at 2
Found [e] starting at 3 and ending at 3

שיעורי תו טווח

מחלקת תו טווח מורכבת משני תווים המופרדים על ידי מקף ( -). כל התווים, החל מהתו משמאל למקף וכלה בתו מימין, הם חלק מהטווח. לדוגמה, הטווח [a-z]מתאים לכל האותיות הקטנות בלטיניות. זה שווה ערך להגדרת מחלקה פשוטה [abcdefghijklmnopqrstuvwxyz]. שקול את הדוגמה הבאה: java RegexDemo [a-c] clown דוגמה זו תתאים רק לתו cשיש לו התאמה ב clown:
regex = [a-c]
input = clown
Found [c] starting at 0 and ending at 0
ביטויים רגילים ב-Java, חלק 2 ביטויים רגילים ב-Java, חלק 3 ביטויים רגילים ב-Java, חלק 4 ביטויים רגילים ב-Java, חלק 5
הערות
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION