正则表达式快速入门
正则表达式是文本匹配的利器,掌握核心语法就能应对大部分搜索替换场景。本文只讲最实用的部分。
什么是正则表达式
正则表达式(Regular Expression,简称 regex)是一种描述文本模式的语言。用简短的规则表达式就能匹配、查找、替换复杂文本。
典型使用场景:
- 搜索替换(编辑器、IDE)
- 数据验证(邮箱、手机号、URL 格式)
- 日志分析
- Web 框架中的路由匹配
基本匹配
普通字符
直接写就是精确匹配:
text
hello 匹配 "hello"
123 匹配 "123"
特殊字符(元字符)
以下字符有特殊含义,需要匹配本身时用 \ 转义:
text
. * + ? ^ $ { } [ ] ( ) | \
常用语法
字符类
| 语法 | 含义 | 示例 |
|---|---|---|
. | 任意单个字符(除换行) | a.b 匹配 aab、a1b |
\d | 数字 [0-9] | \d{3} 匹配 123 |
\w | 单词字符 [a-zA-Z0-9_] | \w+ 匹配 hello_123 |
\s | 空白字符(空格、制表符、换行) | a\sb 匹配 a b |
\D | 非数字 | \D+ 匹配 abc |
\W | 非单词字符 | |
\S | 非空白字符 |
自定义字符类
text
[aeiou] 匹配任意一个元音字母
[a-z] 匹配任意小写字母
[0-9] 等同于 \d
[a-zA-Z] 匹配任意英文字母
[^0-9] 匹配非数字(^ 在 [] 内表示取反)
量词
| 语法 | 含义 | 示例 |
|---|---|---|
* | 0 次或多次 | ab*c 匹配 ac、abc、abbc |
+ | 1 次或多次 | ab+c 匹配 abc、abbc,不匹配 ac |
? | 0 次或 1 次 | colou?r 匹配 color、colour |
{n} | 恰好 n 次 | \d{4} 匹配 4 位数字 |
{n,} | 至少 n 次 | \d{2,} 匹配 2 位及以上数字 |
{n,m} | n 到 m 次 | \d{1,3} 匹配 1 到 3 位数字 |
锚点
| 语法 | 含义 | 示例 |
|---|---|---|
^ | 行首 | ^hello 匹配行首的 hello |
$ | 行尾 | end$ 匹配行尾的 end |
\b | 单词边界 | \bcat\b 匹配 cat,不匹配 cats、scatter |
分组和引用
| 语法 | 含义 |
|---|---|
(...) | 捕获分组 |
\1、\2 | 引用第 N 个分组 |
(?:...) | 非捕获分组(不记录匹配) |
| | 或(cat|dog 匹配 cat 或 dog) |
分组引用常用于替换操作:
text
搜索:(\w+)@(\w+)\.(\w+)
替换:$2@$1.$3
效果:hello@gmail.com → gmail@hello.com
常用正则模式
邮箱
text
[\w.+-]+@[\w-]+\.[\w.]+
简化版,覆盖大多数情况。严格的 RFC 5322 标准正则过于复杂,实际中简化版够用。
手机号(中国大陆)
text
1[3-9]\d{9}
URL
text
https?://[\w\-]+(\.[\w\-]+)+[/\w\-._~:?#@!$&'()*+,;=%]*
IPv4 地址
text
\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}
日期格式(YYYY-MM-DD)
text
\d{4}-\d{2}-\d{2}
修饰符(Flag)
| 标志 | 含义 |
|---|---|
g | 全局匹配(找到所有,不是第一个就停) |
i | 忽略大小写 |
m | 多行模式(^、$ 匹配每行而非整个字符串) |
s | 单行模式(. 匹配换行符) |
在不同场景中使用
JavaScript
javascript
// 测试匹配
const reg = /^\d{4}-\d{2}-\d{2}$/;
reg.test("2026-04-22"); // true
// 提取
const text = "电话:13812345678,邮箱:test@example.com";
const phone = text.match(/1[3-9]\d{9}/)[0];
console.log(phone); // 13812345678
// 替换
const result = "hello world".replace(/(\w+)\s(\w+)/, "$2 $1");
console.log(result); // world hello
Python
python
import re
# 测试匹配
bool(re.match(r"^\d{4}-\d{2}-\d{2}$", "2026-04-22")) # True
# 提取
text = "电话:13812345678,邮箱:test@example.com"
phone = re.search(r"1[3-9]\d{9}", text).group()
print(phone) # 13812345678
# 替换
result = re.sub(r"(\w+)\s(\w+)", r"\2 \1", "hello world")
print(result) # world hello
# 查找所有
numbers = re.findall(r"\d+", "a1 b23 c456")
print(numbers) # ['1', '23', '456']
编辑器 / IDE
在 VS Code、Vim 等编辑器中,搜索框通常直接支持正则表达式:
- VS Code:搜索框右侧点击
.*图标启用正则 - Vim:默认支持,
/pattern搜索,:%s/old/new/g替换
实用技巧
非贪婪匹配(加 ?):
text
贪婪:a.*b 匹配 "aXbYb" 中的 "aXbYb"
非贪婪:a.*?b 匹配 "aXbYb" 中的 "aXb"
默认量词是贪婪的(尽可能多匹配),加 ? 变非贪婪(尽可能少匹配)。
断言(不消耗字符的匹配):
text
(?=...) 正向先行断言(后面是...)
(?!...) 正向先行否定断言(后面不是...)
(?<=...) 正向后行断言(前面是...)
(?<!...) 正向后行否定断言(前面不是...)
示例——匹配价格数字(前面是 $,后面是数字):
text
(?<=\$)\d+
速查表
text
字符类:
. 任意字符
\d \w \s 数字 / 单词字符 / 空白
\D \W \S 取反
[...] 自定义字符类
[^...] 取反
量词:
* + ? 0+次 / 1+次 / 0或1次
{n} {n,} {n,m} 精确/最少/范围
*? +? 非贪婪模式
锚点:
^ $ 行首 / 行尾
\b 单词边界
分组:
(...) 捕获分组
(?:...) 非捕获分组
\| 或
\1 \2 反向引用
断言:
(?=...) 后面是
(?!...) 后面不是
(?<=...) 前面是
(?<!...) 前面不是
常用:
邮箱 [\w.+-]+@[\w-]+\.[\w.]+
手机号 1[3-9]\d{9}
IP地址 \d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}