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