MatchResult
MatchResult
类
理解 Kotlin 中的 MatchResult
类能帮助你高效地使用正则表达式。
这个类提供了关于匹配操作结果的详细信息。例如,如果你用 find()
函数在字符串中查找匹配,它会返回一个 MatchResult
对象(如果没找到则为 null
):
val regex: Regex = """a(\d+)b""".toRegex()
val input = "a123b a4bc"val firstMatch: MatchResult? = regex.find(input)
其他函数
-
matchAt()
和matchEntire()
也会返回MatchResult
。 -
findAll()
会返回一个匹配结果序列(Sequence<MatchResult>
)。
MatchResult
的属性和方法
value
:完整匹配的字符串
println(firstMatch?.value) // 输出: a123b
这个属性表示整个匹配结果的字符串。
range
:匹配在原始字符串中的位置
println(firstMatch?.range) // 输出: 0..4
这个属性表示匹配发生的索引范围。
groups
:捕获组集合(MatchGroupCollection
)
println(firstMatch?.groups)
// 输出: [MatchGroup(value=a123b, range=0..4), MatchGroup(value=123, range=1..3)]
-
第一个组是整个匹配。
-
后面是括号中捕获的每个组。
groupValues
:组对应的值组成的 List<String>
println(firstMatch?.groupValues) // 输出: [a123b, 123]
如果某个组没有捕获内容(如它是可选的且未出现),其值是空字符串。
destructured
:解构捕获组值
val regex = """(\d{4})-(\d{2})-(\d{2})""".toRegex()
val input = "2024-01-01"val secondMatch = regex.find(input)!!val (year, month, day) = secondMatch.destructuredprintln("Year: $year") // 输出: Year: 2024
println("Month: $month") // 输出: Month: 01
println("Day: $day") // 输出: Day: 01
destructured
允许你将捕获组解构为变量,变量数必须与捕获组数匹配。
注意:
!!
会抛出空指针异常,如果find()
返回的是null
。
next()
:获取下一个匹配项
println(firstMatch?.next()?.groupValues) // 输出: [a4b, 4]
与 findAll()
不同,next()
可以更灵活地逐个处理匹配项,适合处理长文本。
实用例子:提高字符串中所有数字的 10%
fun main() {val regex = Regex("""\d+(\.\d+)?""")val input = "The price is $12.99 for the first item, and $9.99 for each additional item."val output = StringBuilder()var match = regex.find(input)var lastIndex = 0while (match != null) {output.append(input.substring(lastIndex, match.range.first))val number = match.value.toDouble()val increasedNumber = number * 1.1output.append("%.2f".format(increasedNumber))lastIndex = match.range.last + 1match = match.next()}output.append(input.substring(lastIndex))println(output)
}
解释:
-
用正则
\d+(\.\d+)?
匹配整数或小数。 -
每次找到一个匹配后:
-
加入前面的非数字部分。
-
解析数字并涨价 10%,保留两位小数。
-
使用
next()
查找下一个匹配。
-
-
最后补上剩下的文本。
输出:
The price is $14.29 for the first item, and $10.99 for each additional item.
非捕获组:(?:...)
有时我们只想分组但不需要捕获:
val regex = Regex("""\d+(\.\d+)?""")
此时:
Groups: [12.99, .99]
Groups: [9.99, .99]
如果我们不需要 .99
被捕获,可以用非捕获组:
val regex = Regex("""\d+(?:\.\d+)?""")
现在结果是:
Groups: [12.99]
Groups: [9.99]
命名捕获组:(?<name>...)
更可读、更易维护:
val regex = """(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})""".toRegex()
val input = "2023-12-31"val matchResult = regex.find(input)println(matchResult?.groups?.get("year")?.value) // 输出: 2023
println(matchResult?.groups?.get("month")?.value) // 输出: 12
println(matchResult?.groups?.get("day")?.value) // 输出: 31
也可使用更简洁写法:
println(matchResult.groups["year"]?.value)
println(matchResult.groups["month"]?.value)
println(matchResult.groups["day"]?.value)
也可以通过索引访问:
println(matchResult.groups[1]?.value) // 同 groups["year"]