正则表达式 – 语法
正则表达式语法(2025年中文讲解)
正则表达式(Regular Expression,简称 regex)是一种强大的文本匹配和处理工具,用于描述字符串的模式,广泛应用于文本搜索、验证、替换等场景。Kotlin、JavaScript、Linux(grep
、sed
等)都支持正则表达式,语法基于 PCRE(Perl Compatible Regular Expressions)标准。2025年,正则表达式仍是编程和运维的核心技能,结合 Kotlin 的 Regex
类、JavaScript 的 RegExp
对象和 Linux 工具,应用在 Android、Web 开发和脚本中。本教程详细讲解正则表达式的语法、核心元字符和实践,基于 MDN、Kotlin 官方文档和 Linux man 页面,适合初学者和开发者。建议用在线工具(如 regex101.com)或 Kotlin Playground 练习。
一、正则表达式语法概览(必知)
- 定义:正则表达式是一组字符模式,用于匹配字符串中的特定内容。
- 核心功能:
- 匹配:检查字符串是否符合模式(如邮箱验证)。
- 搜索:查找匹配的子字符串。
- 替换:将匹配部分替换为新内容。
- 分割:按模式拆分字符串。
- 特点:
- 通用性:跨语言支持(Kotlin、JavaScript、Linux 等)。
- 灵活性:支持复杂模式,如贪婪/非贪婪匹配。
- 空安全:Kotlin 和 JavaScript 需处理空输入。
- 2025年趋势:
- Kotlin 2.0 优化
Regex
类性能,适合 Android 和 KMP。 - JavaScript 中,
RegExp
支持新标志(如v
用于 Unicode)。 - Linux 中,
grep -E
和sed
仍是正则主流工具。
二、核心语法与元字符(必会)
以下按元字符、量词、组等模块讲解,包含示例,代码可在 Kotlin、JavaScript 或 Linux 运行。
1. 基本元字符
元字符 | 描述 | 示例 |
---|---|---|
. | 匹配任意单个字符(除换行符 \n ) | a.c 匹配 abc , a1c |
^ | 匹配字符串开头 | ^abc 匹配 abcde |
$ | 匹配字符串结尾 | abc$ 匹配 xyzabc |
[] | 匹配字符集 | [a-z] 匹配小写字母,[0-9] 匹配数字 |
[^] | 排除字符集 | [^0-9] 匹配非数字 |
| | 或 | cat|dog 匹配 cat 或 dog |
\ | 转义特殊字符 | \. 匹配 . ,\\d 匹配数字 |
示例(Kotlin):
fun main() {
val regex = Regex("a.c")
println(regex.matches("abc")) // 输出:true
println(regex.matches("a1c")) // 输出:true
println(regex.matches("ac")) // 输出:false
}
示例(JavaScript):
const regex = /a.c/;
console.log(regex.test("abc")); // 输出:true
console.log(regex.test("a1c")); // 输出:true
2. 量词
量词 | 描述 | 示例 |
---|---|---|
* | 0 次或多次 | a* 匹配 "" , a , aa |
+ | 1 次或多次 | a+ 匹配 a , aa |
? | 0 次或 1 次 | colou?r 匹配 color , colour |
{n} | 恰好 n 次 | a{3} 匹配 aaa |
{n,} | 至少 n 次 | a{2,} 匹配 aa , aaa |
{n,m} | n 到 m 次 | a{2,4} 匹配 aa , aaa , aaaa |
示例(Linux grep):
echo -e "a\naa\naaa" | grep -E 'a{2}'
输出:
aa
aaa
3. 字符类
字符类 | 描述 | 示例 |
---|---|---|
\d | 数字([0-9]) | \d+ 匹配 123 |
\D | 非数字 | \D+ 匹配 abc |
\w | 字母、数字、下划线([a-zA-Z0-9_]) | \w+ 匹配 hello_123 |
\W | 非 \w | \W+ 匹配 @#$ |
\s | 空白字符(空格、制表符等) | \s+ 匹配 " " |
\S | 非空白字符 | \S+ 匹配 abc |
示例(Kotlin):
fun main() {
val regex = Regex("\\d+")
println(regex.find("Order123")?.value) // 输出:123
}
4. 捕获组与非捕获组
- 捕获组:用
()
定义,捕获匹配内容。
fun main() {
val regex = Regex("(\\w+)@(\\w+\\.com)")
val match = regex.find("alice@example.com")
println(match?.groups?.get(1)?.value) // 输出:alice
println(match?.groups?.get(2)?.value) // 输出:example.com
}
- 非捕获组:用
(?:...)
不存储匹配。
const regex = /(?:http|https):\/\/(\w+)/;
console.log("https://example.com".match(regex)[1]); // 输出:example
5. 贪婪与非贪婪
- 贪婪匹配:默认尽可能多匹配。
const str = "<p>Hello</p><p>World</p>";
console.log(str.match(/<p>.*<\/p>/)[0]); // 输出:<p>Hello</p><p>World</p>
- 非贪婪匹配:用
?
限制最少匹配。
console.log(str.match(/<p>.*?</p>/)[0]); // 输出:<p>Hello</p>
6. 标志(Flags)
标志 | 描述 | 示例 |
---|---|---|
i | 忽略大小写 | /abc/i 匹配 ABC |
g | 全局匹配 | /a/g 匹配所有 a |
m | 多行模式 | /^abc/m 每行匹配 abc |
v | Unicode 模式(JavaScript 新增) | /[🍎]/v 匹配 emoji |
示例(JavaScript):
const regex = /hello/gi;
console.log("Hello HELLO".match(regex)); // 输出:["Hello", "HELLO"]
三、实践示例(综合应用)
- Kotlin 示例(邮箱验证):
fun isValidEmail(email: String): Boolean {
val regex = Regex("^[\\w._%+-]+@[\\w.-]+\\.[a-zA-Z]{2,}$")
return regex.matches(email)
}
fun main() {
println(isValidEmail("alice@example.com")) // 输出:true
println(isValidEmail("invalid@com")) // 输出:false
}
功能:验证邮箱格式(字母/数字/特殊字符@域名.后缀)。
- JavaScript 示例(提取 URL):
const text = "Visit https://example.com and http://test.com";
const regex = /(https?:\/\/[\w.-]+)/g;
const urls = text.match(regex);
console.log(urls); // 输出:["https://example.com", "http://test.com"]
- Linux 示例(查找日志):
#!/bin/bash
grep -E 'ERROR.*2025' /var/log/app.log
功能:查找 /var/log/app.log
中包含“ERROR”和“2025”的行。
- Android 示例(Kotlin + WebView 验证输入):
import android.os.Bundle
import android.webkit.WebView
import android.widget.Button
import android.widget.EditText
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val editText: EditText = findViewById(R.id.editText)
val button: Button = findViewById(R.id.button)
button.setOnClickListener {
val input = editText.text.toString()
val regex = Regex("^[a-zA-Z0-9]{3,}$")
if (regex.matches(input)) {
Toast.makeText(this, "Valid input", Toast.LENGTH_SHORT).show()
} else {
Toast.makeText(this, "Invalid: 3+ alphanumeric", Toast.LENGTH_SHORT).show()
}
}
}
}
布局(res/layout/activity_main.xml
):
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center"
xmlns:android="http://schemas.android.com/apk/res/android">
<EditText
android:id="@+id/editText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:hint="Enter text"/>
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Validate"/>
</LinearLayout>
功能:输入 3+ 位字母数字,点击按钮验证并显示结果。
四、注意事项与最佳实践
- 语法差异:
- Kotlin:使用
Regex
类,需转义\
(如\\d
)。 - JavaScript:用
/pattern/
或new RegExp()
,单\
。 - Linux:
grep -E
和sed
使用 PCRE,注意 shell 转义。
- 性能优化:
- 避免复杂正则(如
.*
),用具体模式提高效率。 - 缓存正则对象:
kotlin val regex = Regex("\\d+").also { it.findAll("123") }
- 空安全:
- Kotlin:检查输入非空:
kotlin fun match(input: String?) = input?.let { Regex("\\d+").matches(it) } ?: false
- JavaScript:处理
null
:javascript const match = str?.match(/\d+/) ?? [];
- 调试:
- 用 regex101.com 测试正则,查看匹配详情。
- 启用
g
标志时,注意lastIndex
(JavaScript):javascript const regex = /\d+/g; regex.lastIndex = 0; // 重置
- 2025年趋势:
- Kotlin:
Regex
结合 Compose 验证表单。 - JavaScript:
v
标志支持 Unicode(如 emoji 匹配)。 - Linux:
grep -P
支持更多 PCRE 特性。 - AI 辅助:VS Code 的 GitHub Copilot 可生成正则表达式。
五、学习建议
- 练习:用 regex101.com 或 Kotlin Playground 实践匹配、替换,验证邮箱或 URL。
- 资源:
- MDN:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_expressions
- Kotlin 文档:https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.text/-regex/
- Linux man:
man grep
- 时间:2-3 天掌握基本语法,1 周熟悉高级模式。
- 实践:写验证脚本(如邮箱、电话)或解析日志。
六、总结
正则表达式必知元字符(.
、^
、*
)、量词、组和标志,必会匹配、搜索、替换和空安全处理。2025年,正则在 Kotlin(表单验证)、JavaScript(Web 交互)和 Linux(日志分析)中不可或缺,结合现代工具更高效。相比其他模式匹配方式,正则表达式通用且强大。
如果需要具体场景代码(如复杂正则或 KMP 示例)或有问题,告诉我,我可以提供更详细解答!