Szukaj…
Idiomy dla dopasowania wyrażenia regularnego w wyrażeniu When
Korzystanie z niezmiennych mieszkańców:
Zużywa mniej przestrzeni poziomej, ale więcej przestrzeni pionowej niż szablon „anonimowych tymczasowych”. Preferowana przez „anonimowych tymczasowych” szablon, jeśli when
wyrażenie jest w pętli - w tym przypadku, definicje regex powinny być umieszczone na zewnątrz pętli.
import kotlin.text.regex
var string = /* some string */
val regex1 = Regex( /* pattern */ )
val regex2 = Regex( /* pattern */ )
/* etc */
when {
regex1.matches(string) -> /* do stuff */
regex2.matches(string) -> /* do stuff */
/* etc */
}
Korzystanie z anonimowych tymczasowych:
Zużywa mniej przestrzeni pionowej, ale więcej przestrzeni poziomej niż szablon „niezmiennych miejscowych”. Nie powinny być stosowane, jeżeli wtedy when
wyrażenie jest w pętli.
import kotlin.text.regex
var string = /* some string */
when {
Regex( /* pattern */ ).matches(string) -> /* do stuff */
Regex( /* pattern */ ).matches(string) -> /* do stuff */
/* etc */
}
Korzystanie ze wzoru gościa:
Ma tę zaletę, że ściśle naśladuje „pełną argumentację” when
składni. Jest to korzystne, ponieważ wyraźniej wskazuje na argument wyrażenia when
, a także wyklucza pewne błędy programisty, które mogą wynikać z konieczności powtarzania argumentu when
w każdym whenEntry
. W tej implementacji można zastosować szablon „niezmiennych miejscowych” lub „anonimowych tymczasowych”.
import kotlin.text.regex
var string = /* some string */
when (RegexWhenArgument(string)) {
Regex( /* pattern */ ) -> /* do stuff */
Regex( /* pattern */ ) -> /* do stuff */
/* etc */
}
I minimalna definicja klasy opakowania dla argumentu when
wyrażenie:
class RegexWhenArgument (val whenArgument: CharSequence) {
operator fun equals(whenEntry: Regex) = whenEntry.matches(whenArgument)
override operator fun equals(whenEntry: Any?) = (whenArgument == whenEntry)
}
Wprowadzenie do wyrażeń regularnych w Kotlinie
Ten post pokazuje, jak korzystać z większości funkcji w klasie Regex
, pracować z wartością null bezpiecznie związaną z funkcjami Regex
, oraz w jaki sposób nieprzetworzone łańcuchy ułatwiają pisanie i odczytywanie wzorców wyrażeń regularnych.
Klasa RegEx
Aby pracować z wyrażeniami regularnymi w Kotlin, musisz użyć klasy Regex(pattern: String)
i wywołać funkcje takie jak find(..)
lub replace(..)
na tym obiekcie wyrażenia regularnego.
Przykład użycia klasy Regex
która zwraca true, jeśli ciąg input
zawiera c lub d:
val regex = Regex(pattern = "c|d")
val matched = regex.containsMatchIn(input = "abc") // matched: true
Zasadniczą rzeczą, którą należy zrozumieć przy wszystkich funkcjach Regex
jest to, że wynik opiera się na dopasowaniu pattern
wyrażenia regularnego i ciągu input
. Niektóre funkcje wymagają pełnego dopasowania, a pozostałe wymagają tylko częściowego dopasowania. Funkcja containsMatchIn(..)
zastosowana w tym przykładzie wymaga częściowego dopasowania i jest wyjaśniona w dalszej części tego postu.
Brak bezpieczeństwa dzięki wyrażeniom regularnym
Zarówno find(..)
i matchEntire(..)
zwrócą MatchResult?
obiekt. The ?
znak po MatchResult
jest konieczny, aby Kotlin mógł bezpiecznie obsługiwać wartość zerową .
Przykład, który pokazuje, jak Kotlin bezpiecznie obsługuje wartość null z funkcji Regex
, gdy funkcja find(..)
zwraca wartość null:
val matchResult =
Regex("c|d").find("efg") // matchResult: null
val a = matchResult?.value // a: null
val b = matchResult?.value.orEmpty() // b: ""
a?.toUpperCase() // Still needs question mark. => null
b.toUpperCase() // Accesses the function directly. => ""
Dzięki funkcji orEmpty()
b
nie może mieć wartości NULL, a znak ?
znak nie jest potrzebny, gdy wywołujesz funkcje na b
.
Jeśli nie zależy ci na bezpiecznej obsłudze wartości zerowych, Kotlin pozwala na pracę z wartościami zerowymi jak w Javie z !!
postacie:
a!!.toUpperCase() // => KotlinNullPointerException
Surowe ciągi znaków we wzorach regularnych
Kotlin zapewnia ulepszenie w stosunku do Java z surowym łańcuchem, który umożliwia pisanie czystych wzorców wyrażeń regularnych bez podwójnych odwrotnych ukośników, które są niezbędne w łańcuchu Java. Surowy ciąg jest reprezentowany potrójnym cytatem:
"""\d{3}-\d{3}-\d{4}""" // raw Kotlin string
"\\d{3}-\\d{3}-\\d{4}" // standard Java string
find (input: CharSequence, startIndex: Int): MatchResult?
Łańcuch input
zostanie dopasowany do pattern
w obiekcie Regex
. Zwraca wynik Matchresult?
obiekt z pierwszym dopasowanym tekstem po parametrze startIndex
lub null
jeśli wzorzec nie pasuje do ciągu input
. MatchResult?
ciąg jest pobierany z MatchResult?
właściwość value
obiektu. Parametr startIndex
jest opcjonalny z wartością domyślną 0.
Aby wyodrębnić pierwszy prawidłowy numer telefonu z ciągu ze szczegółowymi danymi kontaktowymi:
val phoneNumber :String? = Regex(pattern = """\d{3}-\d{3}-\d{4}""")
.find(input = "phone: 123-456-7890, e..")?.value // phoneNumber: 123-456-7890
Bez poprawnego numeru telefonu w ciągu input
zmienna phoneNumber
będzie miała null
.
findAll (input: CharSequence, startIndex: Int): Sequence
Zwraca wszystkie dopasowania z ciągu input
pasującego do pattern
wyrażenia regularnego.
Aby wydrukować wszystkie liczby oddzielone spacją, z tekstu z literami i cyframi:
val matchedResults = Regex(pattern = """\d+""").findAll(input = "ab12cd34ef")
val result = StringBuilder()
for (matchedText in matchedResults) {
result.append(matchedText.value + " ")
}
println(result) // => 12 34
Zmienna matchedResults
to sekwencja z obiektami MatchResult
. W przypadku ciągu input
bez cyfr funkcja findAll(..)
zwróci pustą sekwencję.
matchEntire (input: CharSequence): MatchResult?
Jeśli wszystkie znaki w ciągu input
pasują do pattern
wyrażenia regularnego, zwracany jest ciąg równy input
. W przeciwnym razie null
zostanie zwrócona.
Zwraca ciąg wejściowy, jeśli cały ciąg wejściowy jest liczbą:
val a = Regex("""\d+""").matchEntire("100")?.value // a: 100
val b = Regex("""\d+""").matchEntire("100 dollars")?.value // b: null
mecze (input: CharSequence): Boolean
Zwraca true, jeśli cały ciąg wejściowy pasuje do wzorca wyrażenia regularnego. W przeciwnym razie fałszywe.
Sprawdza, czy dwa ciągi zawierają tylko cyfry:
val regex = Regex(pattern = """\d+""")
regex.matches(input = "50") // => true
regex.matches(input = "50 dollars") // => false
zawieraMatchIn (input: CharSequence): Boolean
Zwraca true, jeśli część ciągu wejściowego pasuje do wzorca wyrażenia regularnego. W przeciwnym razie fałszywe.
Sprawdź, czy dwa ciągi zawierają co najmniej jedną cyfrę:
Regex("""\d+""").containsMatchIn("50 dollars") // => true
Regex("""\d+""").containsMatchIn("Fifty dollars") // => false
split (input: CharSequence, limit: Int): List
Zwraca nową listę bez wszystkich dopasowań wyrażeń regularnych.
Aby zwrócić listy bez cyfr:
val a = Regex("""\d+""").split("ab12cd34ef") // a: [ab, cd, ef]
val b = Regex("""\d+""").split("This is a test") // b: [This is a test]
Na liście jest jeden element dla każdego podziału. Pierwszy ciąg input
ma trzy liczby. To daje listę z trzema elementami.
replace (input: CharSequence, replace: String): String
Zastępuje wszystkie dopasowania pattern
wyrażenia regularnego w ciągu input
ciągiem zastępującym.
Aby zamienić wszystkie cyfry w ciągu na x:
val result = Regex("""\d+""").replace("ab12cd34ef", "x") // result: abxcdxef