Regularni izrazi u Kotlinu

1. Uvod

Upotrebu (ili zlouporabu) regularnih izraza možemo pronaći u gotovo svim vrstama softvera, od brzih skripti do nevjerojatno složenih aplikacija.

U ovom ćemo članku vidjeti kako se koriste regularni izrazi u Kotlinu.

Nećemo raspravljati o sintaksi regularnih izraza; poznavanje regularnih izraza, općenito, potrebno je za adekvatno praćenje članka, a posebno se preporučuje poznavanje sintakse Java Pattern.

2. Postavljanje

Iako regularni izrazi nisu dio jezika Kotlin, oni dolaze sa standardnom bibliotekom.

Vjerojatno ga već imamo kao ovisnost našeg projekta:

 org.jetbrains.kotlin kotlin-stdlib 1.2.21 

Najnoviju verziju kotlin-stdlib možemo pronaći na Maven Central.

3. Stvaranje objekta redovnog izraza

Regularni izrazi su primjeri kotlin.text.Regex razred. Možemo ga stvoriti na nekoliko načina.

Mogućnost je nazvati Regex konstruktor:

Redovni izraz ("a [bc] + d?")

ili možemo nazvati toRegex metoda na a Niz:

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

Napokon, možemo koristiti statičku tvorničku metodu:

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

Osim razlike koja je objašnjena u sljedećem odjeljku, ove su opcije jednake i iznose osobnim željama. Samo ne zaboravite biti dosljedni!

Savjet: regularni izrazi često sadrže znakove koji bi se protumačili kao izlazne sekvence u Niz doslovce. Tako možemo koristiti sirovo Žice da zaboravimo na više razina bijega:

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

3.1. Opcije podudaranja

Oboje Regex konstruktor i toRegex metoda omogućuju nam da odredimo jednu dodatnu opciju ili skup:

Redovni izraz ("a (b | c) + d?", CANON_EQ) Redovni izraz ("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))

Opcije su nabrojane u RegexOption klase, koju smo prikladno statički uvezli u gornjem primjeru:

  • IGNORE_CASE - omogućuje podudaranje bez velikih i malih slova
  • VIŠEVIČEKA - mijenja značenje ^ i $ (vidjeti Uzorak)
  • LITERALNO - uzrokuje da metaznakovi ili izlazne sekvence u uzorku nemaju posebno značenje
  • UNIX_LINES - u ovom načinu rada samo \ n prepoznat je kao linijski završivač
  • KOMENTARI - dopušta razmak i komentare u uzorku
  • DOT_MATCHES_ALL - uzrokuje da se točka podudara s bilo kojim znakom, uključujući terminator retka
  • CANON_EQ - omogućuje ekvivalentnost kanonskom dekompozicijom (vidi Uzorak)

4. Podudaranje

Regularne izraze koristimo prvenstveno za podudaranje unosa Žice, a ponekad i vaditi ili zamjenjivati ​​njihove dijelove.

Sada ćemo detaljno razmotriti metode koje nudi Kotlin Regex razred za podudaranje Žice.

4.1. Provjeravanje djelomičnih ili ukupnih utakmica

U ovim slučajevima korištenja zanimaju nas znajući da li a Niz ili dio a Niz zadovoljava naš regularni izraz.

Ako nam treba samo djelomično podudaranje, možemo koristiti sadržiMatchIn:

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

Ako želimo cjelinu Niz umjesto da se podudaramo, koristimo šibice:

assertTrue (regex.matches ("abcd"))

Imajte na umu da možemo koristiti šibice kao infiksni operator:

assertFalse (regularni izraz podudara se s "xabcdy")

4.2. Izdvajanje odgovarajućih komponenata

U ovim slučajevima upotrebe želimo podudarati se s Niz protiv regularnog izraza i izdvojite dijelove datoteke Niz.

Možda bismo htjeli podudarati cijelu Niz:

val matchResult = regex.matchEntire ("abbccbbd")

Ili bismo možda željeli pronaći prvi podniz koji se podudara:

val matchResult = regex.find ("abcbabbd")

Ili možda pronaći sve odgovarajuće podnizove odjednom, kao a Postavi:

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

U oba slučaja, ako je podudaranje uspješno, rezultat će biti jedan ili više primjeraka MatchResult razred. U sljedećem ćemo odjeljku vidjeti kako ga koristiti.

Ako podudaranje nije uspješno, umjesto toga, ove metode se vraćaju null ili prazna Postavi u slučaju pronađi sve.

4.3. The MatchResult Razred

Primjerci MatchResult klasa predstavljaju uspješna podudaranja nekog ulaznog niza s regularnim izrazom; bilo potpuno ili djelomično podudaranje (vidi prethodni odjeljak).

Kao takvi imaju vrijednost, što je podudarno Niz ili podniz:

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

I oni imaju domet indeksa koji pokazuju koji se dio unosa podudara:

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

4.4. Grupe i destrukturiranje

Također možemo izdvojiti grupe (podudarni podniz) iz MatchResult instance.

Možemo ih dobiti kao Žice:

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

Ili ih također možemo promatrati kao MatchGroup predmeti koji se sastoje od a vrijednost i a domet:

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

Grupa s indeksom 0 uvijek je cijelo podudarno Niz. Indeksi veći od 0, umjesto toga, predstavljaju skupine u regularnom izrazu, odijeljene zagradama, poput ([bc] +) u našem primjeru.

Možemo i destrukturirati MatchResult slučajevi u izjavi o dodjeli:

val regex = "" "([\ w \ s] +) je star (\ d +) godina" "". toRegex () val matchResult = regex.find ("Mickey Mouse ima 95 godina") val (ime, dob ) = matchResult !!. destrukturirani assertEquals ("Mickey Mouse", ime) assertEquals ("95", dob)

4.5. Više podudarnosti

MatchResult također ima a Sljedeći metoda koju možemo koristiti za dobivanje sljedećeg podudaranja unosa Niz protiv regularnog izraza, ako postoji:

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

Kao što vidimo, Sljedeći vraća nulu kad više nema podudaranja.

5. Zamjena

Druga uobičajena upotreba regularnih izraza je zamjenjujući odgovarajuće podnizove s drugim Žice.

U tu svrhu imamo dvije metode dostupne u standardnoj knjižnici.

Jedan, zamijeniti, je za zamjenu svih pojava podudaranja Niz:

val regex = "" "(crvena | zelena | plava)" "". toRegex () val beautiful = "Ruže su crvene, ljubičice su plave" val grim = regex.replace (lijepe, "tamne") assertEquals ("Ruže su tamno, ljubičice su tamne "(mračno)

Drugi, replaceFirst, je za zamjenu samo prvog pojavljivanja:

val sjajna = regex.replaceFirst (lijepa, "duga") assertEquals ("Ruže su duge, ljubičice su plave", sjajne)

5.1. Složene zamjene

Za napredniji scenariji, kada utakmice ne želimo zamijeniti konstantima Žice, ali mi želimo primijeniti transformaciju umjesto toga, Regex i dalje nam daje ono što trebamo.

Uđi zamijeniti preopterećenje uzimanjem zatvarača:

val reallyBeautiful = regex.replace (beautiful) {m -> m.value.toUpperCase () + "!" } assertEquals ("Ruže su CRVENE! Ljubičice SU PLAVE!", stvarnoLijepo)

Kao što vidimo, za svaku utakmicu možemo izračunati zamjenu Niz koristeći tu utakmicu.

6. Cijepanje

Napokon, možda bismo htjeli podijeliti a Niz na popis podnizova prema regularnom izrazu. Opet, Kotlinova Regex nas je pokrio:

val regex = "" "\ W +" "". toRegex () val beautiful = "Ruže su crvene, ljubičice su plave" assertEquals (listOf ("Roses", "are", "red", "Violets", "are" , "plava"), regex.split (lijepa))

Ovdje se regularni izraz podudara s jednim ili više znakova koji nisu riječ, pa je rezultat operacije podjele popis riječi.

Također možemo ograničiti duljinu rezultirajućeg popisa:

assertEquals (listOf ("Ruže", "jesu", "crvene", "Ljubičice su plave"), regex.split (lijepa, 4))

7. Java interoperabilnost

Ako trebamo proslijediti svoj regularni izraz Java kodu ili nekom drugom API-ju JVM jezika koji očekuje instancu java.util.regex.Pattern, možemo jednostavno pretvoriti naš Regex:

regex.toPattern ()

8. Zaključci

U ovom smo članku ispitali podršku za regularne izraze u standardnoj knjižnici Kotlin.

Za daljnje informacije pogledajte referencu Kotlin.

Implementacija svih ovih primjera i isječci koda mogu se naći u projektu GitHub - ovo je Maven projekt, pa bi ga trebalo lako uvesti i pokrenuti kakav jest.