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