Kotlin 中正規表示式簡介
這篇文章展示瞭如何使用 Regex
類中的大多數函式,使用與 Regex
函式安全相關的 null,以及原始字串如何更容易編寫和讀取正規表示式模式。
RegEx 類
要在 Kotlin 中使用正規表示式,你需要使用 Regex(pattern: String)
類並在該正規表示式物件上呼叫 find(..)
或 replace(..)
等函式。
關於如何使用 Regex
類的示例,如果 input
字串包含 c 或 d,則返回 true:
val regex = Regex(pattern = "c|d")
val matched = regex.containsMatchIn(input = "abc") // matched: true
理解所有 Regex
函式的基本要素是結果是基於匹配正規表示式 pattern
和 input
字串。某些功能需要完全匹配,而其餘功能僅需要部分匹配。示例中使用的 containsMatchIn(..)
函式需要部分匹配,本文稍後將對此進行說明。
正規表示式的空安全性
find(..)
和 matchEntire(..)
都將返回 MatchResult?
物件。MatchResult
之後的 ?
字元是 Kotlin 安全處理 null所必需的。
這個示例演示了當 find(..)
函式返回 null 時,Kotlin 如何從 Regex
函式安全地處理 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. => ""
使用 orEmpty()
函式,當你在 b
上呼叫函式時,b
不能為 null,並且不需要 ?
字元。
如果你不關心空值的這種安全處理,Kotlin 允許你使用 !!
字元處理 Java 中的空值:
a!!.toUpperCase() // => KotlinNullPointerException
正規表示式中的原始字串
Kotlin 使用原始字串改進了 Java,這使得編寫純正規表示式模式成為可能,而不需要使用 Java 字串所需的雙反斜槓。原始字串用三重引號表示:
"""\d{3}-\d{3}-\d{4}""" // raw Kotlin string
"\\d{3}-\\d{3}-\\d{4}" // standard Java string
find(輸入:CharSequence,startIndex:Int):MatchResult?
input
字串將與 Regex
物件中的 pattern
匹配。它會返回 Matchresult?
物件,其中第一個匹配的文字位於 startIndex
之後,如果模式與 input
字串不匹配則返回 null
。從 MatchResult?
物件的 value
屬性中檢索結果字串。startIndex
引數是可選的,預設值為 0。
要從包含聯絡人詳細資訊的字串中提取第一個有效電話號碼:
val phoneNumber :String? = Regex(pattern = """\d{3}-\d{3}-\d{4}""")
.find(input = "phone: 123-456-7890, e..")?.value // phoneNumber: 123-456-7890
由於 input
字串中沒有有效的電話號碼,變數 phoneNumber
將為 null
。
findAll(input:CharSequence,startIndex:Int):Sequence
返回與正規表示式匹配的 input
字串中的所有匹配項。
用字母和數字列印出用空格分隔的所有數字:
val matchedResults = Regex(pattern = """\d+""").findAll(input = "ab12cd34ef")
val result = StringBuilder()
for (matchedText in matchedResults) {
result.append(matchedText.value + " ")
}
println(result) // => 12 34
matchedResults
變數是一個包含 MatchResult
物件的序列。如果 input
字串沒有數字,findAll(..)
函式將返回一個空序列。
matchEntire(輸入:CharSequence):MatchResult?
如果 input
字串中的所有字元都與正規表示式 pattern
匹配,則將返回等於 input
的字串。否則,null
將被退回。
如果整個輸入字串是數字,則返回輸入字串:
val a = Regex("""\d+""").matchEntire("100")?.value // a: 100
val b = Regex("""\d+""").matchEntire("100 dollars")?.value // b: null
matches(輸入:CharSequence):Boolean
如果整個輸入字串與正規表示式模式匹配,則返回 true。否則就錯了。
測試兩個字串是否只包含數字:
val regex = Regex(pattern = """\d+""")
regex.matches(input = "50") // => true
regex.matches(input = "50 dollars") // => false
containsMatchIn(input:CharSequence):Boolean
如果輸入字串的一部分與正規表示式模式匹配,則返回 true。否則就錯了。
測試兩個字串是否包含至少一個數字:
Regex("""\d+""").containsMatchIn("50 dollars") // => true
Regex("""\d+""").containsMatchIn("Fifty dollars") // => false
split(輸入:CharSequence,limit:Int):List
返回沒有所有正規表示式匹配的新列表。
要返回沒有數字的列表:
val a = Regex("""\d+""").split("ab12cd34ef") // a: [ab, cd, ef]
val b = Regex("""\d+""").split("This is a test") // b: [This is a test]
列表中有一個元素用於每個拆分。第一個 input
字串有三個數字。這導致列表包含三個元素。
replace(輸入:CharSequence,replacement:String):String
用替換字串替換 input
字串中正規表示式 pattern
的所有匹配項。
要用 x 替換字串中的所有數字:
val result = Regex("""\d+""").replace("ab12cd34ef", "x") // result: abxcdxef