Diqqətinizə Ceff Friesen tərəfindən javaworld veb-saytı üçün yazılmış Java-da müntəzəm ifadələrə dair qısa bələdçinin tərcüməsini təqdim edirik . Oxumaq asanlığı üçün məqaləni bir neçə hissəyə ayırdıq. Java-da müntəzəm ifadələr, 3-cü hissə - 1Java-da müntəzəm ifadələr, 1-ci hissə Java-da müntəzəm ifadələr, 2-ci hissə

Regex API ilə ümumi proqramlaşdırma tapşırıqlarını sadələşdirin

Bu məqalənin 1 və 2-ci hissələrində siz müntəzəm ifadələr və Regex API ilə tanış oldunuz. Siz sinif haqqında öyrəndiniz Patternvə hərfi sətirlərdən istifadə edərək sadə nümunə uyğunluğundan diapazonlar, sərhəd uyğunlaşdırıcıları və kəmiyyət göstəricilərindən istifadə edərək daha mürəkkəb uyğunlaşdırmaya qədər müntəzəm ifadə konstruksiyalarını nümayiş etdirən nümunələri nəzərdən keçirdiniz. Bu və sonrakı hissələrdə birinci hissədə əhatə olunmayan məsələləri nəzərdən keçirəcəyik, siniflərin müvafiq üsullarını öyrənəcəyik PatternMatcher. Siz həmçinin ümumi proqramlaşdırma problemlərini asanlaşdırmaq üçün müntəzəm ifadələrdənPatternSyntaxException istifadə edən iki utiliti öyrənəcəksiniz . Birincisi sənədləşdirmə üçün koddan şərhlər çıxarır. İkincisi, leksik təhlili yerinə yetirmək üçün nəzərdə tutulmuş təkrar istifadə edilə bilən kod kitabxanasıdır - montajçıların, tərtibçilərin və oxşar proqram təminatının vacib komponentidir.

MƏNBƏ KODU YÜKLƏNİR

Bu məqalədəki demo proqramlar üçün bütün mənbə kodunu (JavaWorld üçün Jeff Friesen tərəfindən yaradılmışdır) buradan əldə edə bilərsiniz .

Regex API öyrənmək

Pattern, MatcherPatternSyntaxExceptionRegex API-ni təşkil edən üç sinifdir. Onların hər biri kodunuzda müntəzəm ifadələrdən istifadə etməyə imkan verən üsulları təqdim edir.

Pattern sinfinin metodları

Sinif nümunəsi Patterntərtib edilmiş nizamlı ifadədir və nümunə kimi də tanınır. Nümunə uyğunlaşdırma əməliyyatlarının performansını yaxşılaşdırmaq üçün müntəzəm ifadələr tərtib edilir. Aşağıdakı statik üsullar kompilyasiyanı dəstəkləyir.
  • Pattern compile(String regex)məzmunu regexyenidə saxlanılan aralıq təmsilçiliyə tərtib edir Pattern. Bu üsul ya müvəffəqiyyətli olarsa, obyektə istinad qaytarır, ya da PatternSyntaxExceptionetibarsız müntəzəm ifadə sintaksisi aşkar edilərsə, istisna atır. MatcherBu obyekt tərəfindən istifadə edilən və ya ondan qaytarılan sinifin hər hansı obyekti Patternböyük hərflərə həssas axtarış kimi standart parametrlərindən istifadə edir. Nümunə olaraq, kod parçası nöqtə simvolu ilə başlayan sətirlərə uyğunlaşdırmaq üçün müntəzəm ifadənin tərtib edilmiş təsvirini saxlayan Pattern p = Pattern.compile("(?m)^\\."); obyekt yaradır .Pattern

  • Pattern compile(String regex, int flags)ilə eyni problemi həll edir Pattern compile(String regex), lakin nəzərə alaraq flags: OR tipli bit bayraqları üçün bit sabitləri dəsti. Sinif bitwise OR istifadə edərək birləşdirilə bilən Patternsabitləri elan edir (məsələn, ) və arqument kimi ötürülür .CANON_EQ, CASE_INSENSITIVE, COMMENTS, DOTALL, LITERAL, MULTILINE, UNICODE_CASE, UNICODE_CHARACTER_CLASS и UNIX_LINESCASE_INSENSITIVE | DOTALLflags

  • İstisna olmaqla CANON_EQ, LITERAL и UNICODE_CHARACTER_CLASS, bu sabitlər 1-ci hissədə nümayiş etdirilən iç-içə bayraq ifadələrinə alternativdir. Əgər sinifdə təyin olunanlardan başqa bayraq sabiti ilə qarşılaşarsa Pattern, metod Pattern compile(String regex, int flags) istisna atır java.lang.IllegalArgumentException. Məsələn, Pattern p = Pattern.compile("^\\.", Pattern.MULTILINE);əvvəlki nümunəyə ekvivalentdir, sabit Pattern.MULTILINEvə yuvalanmış bayraq ifadəsi (?m)eyni şeyi edir.
PatternBəzən istifadə etdiyi bayraqlarla birlikdə obyektə yığılmış müntəzəm ifadənin orijinal sətirinin surətini əldə etmək lazımdır . Bunu etmək üçün aşağıdakı üsullara zəng edə bilərsiniz:
  • String pattern()a şəklində tərtib edilmiş orijinal müntəzəm ifadə sətirini qaytarır Pattern.

  • int flags()obyektin bayraqlarını qaytarır Pattern.
Obyekti qəbul etdikdən sonra adətən nümunə uyğunlaşdırma əməliyyatlarını yerinə yetirmək üçün Patternobyekti əldə etmək üçün istifadə olunur . MatcherMetod obyekt nümunəsinə uyğunluq üçün mətni axtaran Matcher matcher(Charsequence input)obyekt yaradır . Zəng edildikdə, bu obyektə istinad qaytarır . Məsələn, əmr dəyişənin istinad etdiyi obyekt üçün qaytarır . MatcherinputPatternMatcherMatcher m = p.matcher(args[1]);MatcherPatternp
Birdəfəlik axtarış
static boolean matches(String regex, CharSequence input)Sinif metodu Patternobyektlərin yaradılmasına PatternMatcherşablondan istifadə edərək birdəfəlik axtarışa qənaət etməyə imkan verir. inputNümunə uyğundursa bu üsul doğru qaytarır regex, əks halda false qaytarır. Normal ifadə sintaksis xətası ehtiva edirsə, metod istisna atır PatternSyntaxException. Məsələn, ifadənin yalnız boşluq və kiçik hərflərdən ibarət olduğunu təsdiqləyən System.out.println(Pattern.matches("[a-z[\\s]]*", "all lowercase letters and whitespace only"));çap edir . trueall lowercase letters and whitespace only
Java-da müntəzəm ifadələr, 3-cü hissə - 2

Mətnin bölünməsi

Əksər tərtibatçılar, mətnə ​​əsaslanan işçi hesabını bir sıra sahələrə çevirmək kimi daxil edilən mətni komponent hissələrinə bölmək üçün ən azı bir dəfə yazılmış koda malikdirlər. Sinif Patterniki mətn bölmə metodundan istifadə edərək bu yorucu tapşırığı daha rahat həll etmək imkanı verir:
  • Metod tapılan uyğunluqlara görə obyekt nümunəsinə String[] split(CharSequence text, int limit)bölünür və nəticələri massivdə qaytarır. Hər bir massiv elementi nümunəyə uyğun mətn fraqmenti (və ya mətnin sonu) ilə növbəti ardıcıllıqdan ayrılmış mətn ardıcıllığını təyin edir. Massivin elementləri göründükləri ardıcıllıqla eynidir .textPatterntext

    limitBu üsulda massiv elementlərinin sayı tapılacaq uyğunluqların sayına nəzarət edən parametrdən asılıdır .

    • Müsbət dəyər uyğunluqdan çox axtarmır limit-1və massivin uzunluğu limitelementlərdən çox deyil.
    • Dəyər mənfi olarsa, bütün mümkün uyğunluqlar axtarılır və massivin uzunluğu ixtiyari ola bilər.
    • Dəyər sıfırdırsa, bütün mümkün uyğunluqlar axtarılır, massivin uzunluğu ixtiyari ola bilər və sonundakı boş sətirlər atılır.

  • Metod String[] split(CharSequence text)limit arqumenti kimi 0 ilə əvvəlki metodu çağırır və çağırışının nəticəsini qaytarır.
split(CharSequence text)Aşağıda işçi hesabının ad, yaş, poçt ünvanı və əmək haqqının ayrı-ayrı sahələrinə bölünməsi probleminin həlli metodunun nəticələri verilmişdir :
Pattern p = Pattern.compile(",\\s");
String[] fields = p.split("John Doe, 47, Hillsboro Road, 32000");
for (int i = 0; i < fields.length; i++)
   System.out.println(fields[i]);
Yuxarıdakı kod, dərhal bir boşluq simvolundan sonra vergül simvolunu tapmaq üçün müntəzəm ifadəni təsvir edir. Onun icrasının nəticələrini təqdim edirik:
John Doe
47
Hillsboro Road
32000

Şablon predikatlar və Streams API

Java 8-də sinifdə Patternbir üsul ortaya çıxdı . Bu üsul nümunəyə uyğun gəlmək üçün istifadə olunan predikat (boolean dəyəri olan funksiya) yaradır. Bu metodun istifadəsi aşağıdakı kod parçasında göstərilir: Predicate asPredicate()
List progLangs = Arrays.asList("apl", "basic", "c", "c++", "c#", "cobol", "java", "javascript", "perl", "python", "scala");
Pattern p = Pattern.compile("^c");
progLangs.stream().filter(p.asPredicate()).forEach(System.out::println);
Bu kod proqramlaşdırma dili adlarının siyahısını yaradır, sonra hərfi ilə başlayan bütün adları tapmaq üçün nümunə tərtib edir c. Yuxarıdakı kodun son sətri mənbə kimi bu siyahı ilə ardıcıl məlumat axınının qəbulunu həyata keçirir. asPredicate()O , ad hərflə başlayanda doğru olanı qaytaran cvə axın vasitəsilə təkrarlanan, uyğun adları standart çıxışa çap edən Boolean funksiyasından istifadə edərək filtr qurur . Bu sonuncu sətir 1-ci hissədən RegexDemo tətbiqindən tanış olan aşağıdakı müntəzəm dövrəyə bərabərdir:
for (String progLang: progLangs)
   if (p.matcher(progLang).find())
      System.out.println(progLang);

Uyğun sinif metodları

Sinfin nümunəsi, Matchersinfin tərtib edilmiş müntəzəm ifadəsini şərh etməklə simvollar ardıcıllığı üzərində nümunə uyğunlaşdırma əməliyyatlarının yerinə yetirilməsi mexanizmini təsvir edir Pattern. Sinfin obyektləri Matchernümunə axtarış əməliyyatlarının müxtəlif növlərini dəstəkləyir:
  • Metod boolean find()növbəti uyğunluq üçün daxil edilmiş mətni axtarır. Bu üsul skan etməyə ya göstərilən mətnin əvvəlində, ya da əvvəlki uyğunluqdan sonrakı ilk simvolda başlayır. İkinci seçim yalnız bu metoda əvvəlki çağırış doğru olduqda və həlledici sıfırlanmadıqda mümkündür. İstənilən halda, axtarış uğurlu olarsa, məntiqi dəyər true qaytarılır. Bu metodun nümunəsini RegexDemo1-ci hissədə tapa bilərsiniz.

  • Metod boolean find(int start)uyğunlaşdırıcını sıfırlayır və növbəti uyğunluq üçün mətni axtarır. Baxış parametrlə müəyyən edilmiş mövqedən başlayır start. Axtarış uğurlu olarsa, boolean dəyəri doğru qaytarılır. Məsələn, m.find(1);mövqedən başlayaraq mətni skan edir 1(0 mövqeyi nəzərə alınmır). Parametrdə startmənfi dəyər və ya uyğunlaşdırıcı mətn uzunluğundan böyük dəyər varsa, metod istisna atır java.lang.IndexOutOfBoundsException.

  • Metod boolean matches()bütün mətni nümunəyə uyğunlaşdırmağa çalışır. Bütün mətn naxışa uyğundursa, bu, doğru bir məntiqi dəyəri qaytarır. Məsələn, simvol söz simvolu olmadığı üçün kod Pattern p = Pattern.compile("\\w*"); Matcher m = p.matcher("abc!"); System.out.println(p.matches());çıxış edir .false!

  • Metod boolean lookingAt()göstərilən mətni nümunə ilə uyğunlaşdırmağa çalışır. Mətnin hər hansı bir hissəsi naxışa uyğun gəlirsə, bu üsul doğru qaytarır. Metoddan fərqli olaraq matches();, bütün mətn nümunəyə uyğun gəlməməlidir. Məsələn, mətnin əvvəli yalnız söz əmələ gətirən simvollardan ibarət olduğu üçün Pattern p = Pattern.compile("\\w*"); Matcher m = p.matcher("abc!"); System.out.println(p.lookingAt());çıxış edəcək .trueabc!

Sinif obyektlərindən fərqli olaraq Pattern, sinif obyektləri Matcherdövlət məlumatlarını saxlayır. Bəzən nümunə axtarışı başa çatdıqdan sonra bu məlumatı təmizləmək üçün uyğunlaşdırıcını sıfırlamağınız lazım ola bilər. Həlledicini yenidən qurmaq üçün aşağıdakı üsullar mövcuddur:
  • Metod Matcher reset(), sona əlavə olunacaq mövqe də daxil olmaqla, uyğunlaşdırıcının vəziyyətini sıfırlayır (0-a sıfırlanır). Növbəti nümunə axtarış əməliyyatı uyğunlaşdırıcı mətnin əvvəlindən başlayır. Cari obyektə istinad qaytarır Matcher. Məsələn, m.reset();istinad edilən həlledicini sıfırlayır m.

  • Metod Matcher reset(CharSequence text)həlledici vəziyyətini sıfırlayır və yeni həlledici mətni təyin edir text. Növbəti nümunə axtarış əməliyyatı yeni uyğunlaşdırıcı mətnin əvvəlində başlayır. Cari obyektə istinad qaytarır Matcher. Məsələn, m.reset("new text");istinad edilən həlledicini sıfırlayır mvə yeni həlledici mətni olaraq təyin edir "new text".

Java-da müntəzəm ifadələr, 3-3-cü hissə

Sona mətn əlavə edilir

Sona əlavə olunacaq uyğunlaşdırıcının mövqeyi, tipli obyektin sonuna əlavə olunan uyğunlaşdırıcı mətnin başlanğıcını müəyyən edir java.lang.StringBuffer. Aşağıdakı üsullar bu mövqedən istifadə edir:
  • Metod uyğunlaşdırıcı mətn simvollarını oxuyur və onları arqumentin istinad etdiyi Matcher appendReplacement(StringBuffer sb, String replacement)obyektin sonuna əlavə edir . Bu üsul əvvəlki nümunə uyğunluğundan əvvəlki son simvolda oxumağı dayandırır. Sonra, metod arqumentlə istinad edilən obyektin simvollarını obyektin sonuna əlavə edir (sətirdə əvvəlki axtarış zamanı çəkilmiş mətn ardıcıllığına istinadlar ola bilər; bunlar çəkilən simvollar və qrup nömrələri ilə müəyyən edilir). Nəhayət, metod son uyğun gələn simvolun mövqeyinə əlavə olunacaq uyğunlaşdırıcı mövqeyinin dəyərini təyin edir və daha sonra cari uyğunlaşdırıcıya istinad qaytarır.StringBuffersbStringreplacementStringBufferreplacement($)

  • Uyğunlaşdırıcı hələ uyğunluq tapmayıbsa və ya əvvəlki axtarış cəhdi uğursuz olarsa, metod Matcher appendReplacement(StringBuffer sb, String replacement)istisna yaradır . Xətt nümunədə olmayan bir tutma qrupunu təyin edərsə , java.lang.IllegalStateExceptionistisna atır ).IndexOutOfBoundsExceptionreplacement

  • Metod StringBuffer appendTail(StringBuffer sb)bütün mətni obyektə əlavə edir StringBuffervə həmin obyektə istinadı qaytarır. Sonuncu metod çağırışından sonra qalan mətni obyektə köçürmək üçün appendReplacement(StringBuffer sb, String replacement)metodu çağırın .appendTail(StringBuffer sb)StringBuffer

Tutulan qruplar
1-ci hissədən xatırladığınız kimi, ələ keçirmə qrupu mötərizədə ( ) metasimvollar içərisində olan simvollar ardıcıllığıdır (). Bu konstruksiyanın məqsədi tapılmış simvolları sonradan nümunə uyğunluğu zamanı təkrar istifadə etmək üçün saxlamaqdır. Nümunə axtarışı zamanı tutulan qrupdakı bütün simvollar vahid bütöv kimi qəbul edilir.
Aşağıdakı kod mənbə mətndəki simvol ardıcıllığının bütün baş vermələrini ilə əvəz etmək üçün appendReplacement(StringBuffer sb, String replacement)və metodlarını çağırır : appendTail(StringBuffer sbcatcaterpillar
Pattern p = Pattern.compile("(cat)");
Matcher m = p.matcher("one cat, two cats, or three cats on a fence");
StringBuffer sb = new StringBuffer();
while (m.find())
   m.appendReplacement(sb, "$1erpillar");
m.appendTail(sb);
System.out.println(sb);
Əvəz edilmiş mətndə tutulan qrupdan və ona istinaddan istifadə etmək proqrama erpillarhər baş verəndən sonra daxil etməyi əmr edir cat. Bu kodun icrasının nəticəsi belə görünür: one caterpillar, two caterpillars, or three caterpillars on a fence

Mətnin dəyişdirilməsi

Sinif Matcherbizə mətnin dəyişdirilməsi üçün iki üsul təqdim edir appendReplacement(StringBuffer sb, String replacement). Bu üsullardan istifadə edərək, siz [əvəz edilmiş mətnin] ilk baş verməsini və ya bütün hadisələri əvəz edə bilərsiniz:
  • Metod String replaceFirst(String replacement)uyğunlaşdırıcını sıfırlayır, yeni obyekt yaradır String, uyğunlaşdırıcı mətnin bütün simvollarını (ilk uyğunluğa qədər) bu sətirə köçürür, simvolları onun sonuna qədər əlavə edir replacement, qalan simvolları sətirə köçürür və geri qaytarır. obyekt String(sətirdə replacementdollar simvollarından və tutulan qrup nömrələrindən istifadə edərək əvvəlki axtarış mətn ardıcıllığı zamanı tutulanlara istinadlar ola bilər).

  • Metod String replaceAll(String replacement)metoda bənzər şəkildə işləyir String replaceFirst(String replacement), lakin replacementtapılan bütün uyğunluqları sətirdəki simvollarla əvəz edir.

Normal ifadə \s+giriş mətnində bir və ya daha çox boşluq simvolu axtarır. Aşağıda bu müntəzəm ifadədən istifadə edəcəyik və replaceAll(String replacement)dublikat boşluqları silmək üçün bir üsul çağıracağıq:
Pattern p = Pattern.compile("\\s+");
Matcher m = p.matcher("Удаляем      \t\t лишние пробелы.   ");
System.out.println(m.replaceAll(" "));
Nəticələr budur: Удаляем лишние пробелы. Java-da müntəzəm ifadələr, 4-cü hissə Java-da müntəzəm ifadələr, 5-ci hissə