Kotlin正则表达式
外观
Kotlin正则表达式[编辑 | 编辑源代码]
正则表达式(Regular Expression,简称Regex)是一种强大的文本处理工具,用于在字符串中匹配、查找、替换或提取特定模式的文本。在Kotlin中,正则表达式通过`Regex`类实现,并提供了丰富的API来简化字符串操作。本章将详细介绍Kotlin中正则表达式的基本语法、常见用法和实际应用场景。
基本概念[编辑 | 编辑源代码]
正则表达式由一系列字符和特殊符号组成,用于定义字符串的匹配规则。以下是正则表达式的基本组成部分:
- 字面字符:普通字符(如`a`、`1`)直接匹配自身。
- 元字符:具有特殊含义的字符,如`.`(匹配任意字符)、`*`(匹配前一个字符0次或多次)。
- 字符类:用`[]`定义,匹配其中任意一个字符,如`[abc]`匹配`a`、`b`或`c`。
- 量词:指定匹配次数,如`+`(1次或多次)、`?`(0次或1次)。
- 分组:用`()`将部分模式分组,便于后续引用或操作。
创建正则表达式[编辑 | 编辑源代码]
在Kotlin中,可以通过以下方式创建正则表达式:
1. 使用`Regex`构造函数:
val regex = Regex("a.b") // 匹配"a"后跟任意字符,再跟"b"
2. 使用字符串的`toRegex()`扩展函数:
val regex = "a.b".toRegex()
3. 使用三引号字符串(避免转义特殊字符):
val regex = """\d{3}-\d{2}-\d{4}""".toRegex() // 匹配美国社保号格式
常用方法[编辑 | 编辑源代码]
Kotlin的`Regex`类提供了以下常用方法:
1. 匹配整个字符串(`matches`)[编辑 | 编辑源代码]
检查字符串是否完全匹配正则表达式:
val regex = Regex("a.b")
println(regex.matches("axb")) // 输出: true
println(regex.matches("axyb")) // 输出: false
2. 查找匹配项(`find`和`findAll`)[编辑 | 编辑源代码]
- `find`:返回第一个匹配项(`MatchResult?`)
- `findAll`:返回所有匹配项的序列
val text = "Kotlin 1.6 released in 2021"
val regex = Regex("\\d+") // 匹配一个或多个数字
val firstMatch = regex.find(text)
println(firstMatch?.value) // 输出: 1
val allMatches = regex.findAll(text).toList()
allMatches.forEach { println(it.value) } // 输出: 1, 6, 2021
3. 替换匹配项(`replace`和`replaceFirst`)[编辑 | 编辑源代码]
- `replace`:替换所有匹配项
- `replaceFirst`:仅替换第一个匹配项
val text = "foo bar baz"
val regex = Regex("ba.")
println(regex.replace(text, "XXX")) // 输出: foo XXX XXX
println(regex.replaceFirst(text, "XXX")) // 输出: foo XXX baz
4. 分割字符串(`split`)[编辑 | 编辑源代码]
根据正则表达式分割字符串:
val text = "apple,banana;cherry"
val regex = Regex("[,;]") // 匹配逗号或分号
val parts = regex.split(text)
println(parts) // 输出: [apple, banana, cherry]
正则表达式语法详解[编辑 | 编辑源代码]
以下是一些常用的正则表达式语法:
字符类[编辑 | 编辑源代码]
- `[abc]`:匹配`a`、`b`或`c`
- `[^abc]`:匹配除`a`、`b`、`c`外的任意字符
- `[a-z]`:匹配任意小写字母
- `[A-Z0-9]`:匹配大写字母或数字
预定义字符类[编辑 | 编辑源代码]
- `\d`:数字,等价于`[0-9]`
- `\D`:非数字,等价于`[^0-9]`
- `\s`:空白字符(空格、制表符等)
- `\w`:单词字符(字母、数字、下划线)
量词[编辑 | 编辑源代码]
- `X?`:0次或1次
- `X*`:0次或多次
- `X+`:1次或多次
- `X{n}`:恰好n次
- `X{n,}`:至少n次
- `X{n,m}`:n到m次
边界匹配[编辑 | 编辑源代码]
- `^`:字符串开头
- `$`:字符串结尾
- `\b`:单词边界
分组与捕获[编辑 | 编辑源代码]
分组允许将部分正则表达式组合起来,并捕获匹配的子字符串:
val text = "John: 30, Alice: 25"
val regex = Regex("(\\w+): (\\d+)") // 两个分组:姓名和年龄
val matches = regex.findAll(text).toList()
matches.forEach { match ->
println("Name: ${match.groupValues[1]}, Age: ${match.groupValues[2]}")
}
// 输出:
// Name: John, Age: 30
// Name: Alice, Age: 25
实际应用案例[编辑 | 编辑源代码]
案例1:验证电子邮件格式[编辑 | 编辑源代码]
fun isValidEmail(email: String): Boolean {
val regex = Regex("^[\\w.-]+@[\\w.-]+\\.[a-z]{2,}\$", RegexOption.IGNORE_CASE)
return regex.matches(email)
}
println(isValidEmail("test@example.com")) // true
println(isValidEmail("invalid.email")) // false
案例2:提取HTML标签内容[编辑 | 编辑源代码]
val html = "<h1>Title</h1><p>Paragraph</p>"
val regex = Regex("<.*?>(.*?)<.*?>")
val contents = regex.findAll(html).map { it.groupValues[1] }.toList()
println(contents) // 输出: [Title, Paragraph]
案例3:日志文件分析[编辑 | 编辑源代码]
假设日志格式为`[2023-01-01] ERROR: File not found`:
val log = "[2023-01-01] ERROR: File not found"
val regex = Regex("\\[(.*?)\\] (\\w+): (.*)")
val match = regex.find(log)!!
println("Date: ${match.groupValues[1]}")
println("Level: ${match.groupValues[2]}")
println("Message: ${match.groupValues[3]}")
// 输出:
// Date: 2023-01-01
// Level: ERROR
// Message: File not found
性能优化建议[编辑 | 编辑源代码]
1. 预编译正则表达式:如果多次使用同一正则表达式,建议将其定义为全局常量:
val EMAIL_REGEX = Regex("^[\\w.-]+@[\\w.-]+\\.[a-z]{2,}\$")
2. 避免贪婪匹配:默认量词(`*`、`+`)是贪婪的,可能影响性能。在不需要时使用惰性匹配(`*?`、`+?`)。
3. 使用具体字符类:`\d`比`[0-9]`更易读,但后者在某些情况下性能更好。
常见问题与陷阱[编辑 | 编辑源代码]
- 转义字符:在字符串中需对反斜杠转义(`\\d`),或使用三引号字符串(`"""\d"""`)。
- 贪婪匹配:`".*"`会匹配到字符串末尾,可能不符合预期。
- Unicode字符:默认情况下,`\w`等字符类仅匹配ASCII字符,可使用`RegexOption.UNICODE_CHARACTER_CLASS`启用Unicode支持。
总结[编辑 | 编辑源代码]
Kotlin的正则表达式功能强大且易于使用,通过`Regex`类和丰富的API可以高效处理文本匹配、提取和替换任务。掌握正则表达式能显著提升字符串处理的灵活性和效率。建议从简单模式开始练习,逐步掌握复杂表达式的编写技巧。