跳到主要内容

正则表达式速查表

快速查阅正则表达式的语法和常用模式。

基础语法

字符匹配

模式说明示例
abc精确匹配/abc/ 匹配 "abc"
.任意字符(除换行)/a.c/ 匹配 "abc", "a1c"
\转义字符/a\*b/ 匹配 "a*b"
|或操作/a|b/ 匹配 "a" 或 "b"

字符类

模式说明等价于
[abc]a、b 或 c 中的任意一个-
[^abc]除 a、b、c 外的任意字符-
[a-z]a 到 z 的任意小写字母-
[A-Z]A 到 Z 的任意大写字母-
[0-9]0 到 9 的任意数字-
[a-zA-Z]任意字母-
[a-zA-Z0-9]任意字母或数字-

预定义字符类

模式说明等价于
\d数字[0-9]
\D非数字[^0-9]
\w单词字符[a-zA-Z0-9_]
\W非单词字符[^a-zA-Z0-9_]
\s空白字符[ \t\n\r\f\v]
\S非空白字符[^ \t\n\r\f\v]

量词

模式说明示例
*零次或多次/a*/ 匹配 "", "a", "aaa"
+一次或多次/a+/ 匹配 "a", "aaa"
?零次或一次/a?/ 匹配 "", "a"
{n}恰好 n 次/a{3}/ 匹配 "aaa"
{n,}至少 n 次/a{2,}/ 匹配 "aa", "aaa"
{n,m}n 到 m 次/a{2,4}/ 匹配 "aa", "aaa", "aaaa"
*?非贪婪零次或多次匹配尽可能少的字符
+?非贪婪一次或多次匹配尽可能少的字符
??非贪婪零次或一次匹配尽可能少的字符

位置锚点

模式说明示例
^字符串开头/^abc/ 匹配以 abc 开头
$字符串结尾/abc$/ 匹配以 abc 结尾
\b单词边界/\bword\b/ 匹配完整单词
\B非单词边界/\Bword\B/ 匹配单词内部

分组与捕获

模式说明示例
(abc)捕获分组/(\d+)-(\d+)/
(?:abc)非捕获分组/(?:\d{4})-(\d{2})/
(?<name>abc)命名分组/(?<year>\d{4})/
\1, \2反向引用/(")[^"]*\1/
\k<name>命名反向引用/(?<q>["'])[^\k<q>]*\k<q>/

零宽断言

模式说明示例
(?=abc)正向先行断言/\d(?=px)/ 匹配后面是 px 的数字
(?!abc)负向先行断言/\d(?!px)/ 匹配后面不是 px 的数字
(?<=abc)正向后行断言/(?<=\$)\d+/ 匹配前面是 $ 的数字
(?<!abc)负向后行断言/(?<!\$)\d+/ 匹配前面不是 $ 的数字

标志(修饰符)

标志说明JavaScriptPython
i忽略大小写/abc/ire.I
g全局匹配/abc/g-
m多行模式/abc/mre.M
sdotAll 模式/abc/sre.S
uUnicode 模式/abc/u默认
y粘性匹配/abc/y-

常用正则表达式模式

验证类

// 邮箱(简化版)
/^[\w.-]+@[\w.-]+\.\w{2,}$/

// 邮箱(完整版)
/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/

// 中国手机号
/^1[3-9]\d{9}$/

// 固话号码(带区号)
/^0\d{2,3}-?\d{7,8}$/

// 身份证号(中国大陆)
/^[1-9]\d{5}(18|19|20)\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])\d{3}[\dXx]$/

// IPv4 地址
/^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/

// IPv6 地址(简化版)
/^([\da-fA-F]{1,4}:){7}[\da-fA-F]{1,4}$/

// URL
/^https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)$/

// 日期(YYYY-MM-DD)
/^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])$/

// 时间(HH:MM:SS)
/^([01]\d|2[0-3]):[0-5]\d:[0-5]\d$/

// 密码(至少8位,包含大小写字母和数字)
/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[a-zA-Z\d]{8,}$/

// 密码(至少8位,包含大小写字母、数字和特殊字符)
/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$/

// 中文姓名(2-4个汉字)
/^[\u4e00-\u9fa5]{2,4}$/

// 邮政编码
/^\d{6}$/

提取类

// 提取 HTML 标签
/<(\w+)[^>]*>([^<]*)<\/\1>/g

// 提取 URL
/https?:\/\/[^\s]+/g

// 提取邮箱
/[\w.-]+@[\w.-]+\.\w{2,}/g

// 提取手机号
/1[3-9]\d{9}/g

// 提取中文
/[\u4e00-\u9fa5]+/g

// 提取 Markdown 链接
/\[([^\]]+)\]\(([^)]+)\)/g

// 提取图片地址
/<img[^>]+src=["']([^"']+)["'][^>]*>/gi

// 提取视频地址
/<video[^>]+src=["']([^"']+)["'][^>]*>/gi

替换类

// 去除所有 HTML 标签
str.replace(/<[^>]+>/g, "")

// 去除多余空白
str.replace(/\s+/g, " ")

// 去除行首行尾空白
str.replace(/^\s+|\s+$/g, "")
// 或使用 trim()

// 驽峰命名转下划线
"helloWorld".replace(/([a-z])([A-Z])/g, "$1_$2").toLowerCase()
// 结果: "hello_world"

// 下划线转驼峰命名
"hello_world".replace(/_([a-z])/g, (_, char) => char.toUpperCase())
// 结果: "helloWorld"

// 手机号码脱敏
"13812345678".replace(/(\d{3})\d{4}(\d{4})/, "$1****$2")
// 结果: "138****5678"

// 身份证号脱敏
"110101199001011234".replace(/(\d{6})\d{8}(\d{4})/, "$1********$2")
// 结果: "110101********1234"

// 日期格式转换(YYYY-MM-DD -> DD/MM/YYYY)
"2024-03-15".replace(/(\d{4})-(\d{2})-(\d{2})/, "$3/$2/$1")
// 结果: "15/03/2024"

各语言正则表达式用法

JavaScript

// 创建正则
const regex = /pattern/flags;
const regex = new RegExp("pattern", "flags");

// 测试
regex.test(string); // 返回 true/false

// 匹配
string.match(regex); // 返回数组或 null
string.matchAll(regex); // 返回迭代器
regex.exec(string); // 返回数组或 null

// 查找
string.search(regex); // 返回索引或 -1

// 替换
string.replace(regex, replacement);
string.replaceAll(regex, replacement);

// 分割
string.split(regex);

// 常甦标志
// i - 忽略大小写
// g - 全局匹配
// m - 多行模式
// s - dotAll 模式
// u - Unicode 模式
// y - 粘性匹配

Python

import re

# 创建模式
pattern = re.compile(r"pattern", flags)

# 测试
pattern.match(string) # 从开始匹配
pattern.search(string) # 搜索第一个匹配
pattern.fullmatch(string) # 完整匹配

# 匹配所有
pattern.findall(string) # 返回列表
pattern.finditer(string) # 返回迭代器

# 替换
pattern.sub(replacement, string)
pattern.subn(replacement, string) # 返回 (新字符串, 替换次数)

# 分割
pattern.split(string)

# 常用标志
# re.I / re.IGNORECASE - 忽略大小写
# re.M / re.MULTILINE - 多行模式
# re.S / re.DOTALL - . 匹配换行
# re.X / re.VERBOSE - 详细模式(忽略空白和注释)
# re.A / re.ASCII - ASCII 模式

Java

import java.util.regex.*;

// 创建模式
Pattern pattern = Pattern.compile("regex", flags);
Matcher matcher = pattern.matcher(input);

// 测试
matcher.matches(); // 完整匹配
matcher.find(); // 查找下一个匹配
matcher.lookingAt(); // 从开始匹配

// 获取结果
matcher.group(); // 完整匹配
matcher.group(1); // 第1个分组
matcher.group("name"); // 命名分组

// 替换
matcher.replaceAll(replacement);
matcher.replaceFirst(replacement);

// 常用标志
// Pattern.CASE_INSENSITIVE - 忽略大小写
// Pattern.MULTILINE - 多行模式
// Pattern.DOTALL - . 匹配换行
// Pattern.UNICODE_CASE - Unicode 大小写

Go

package main

import (
"fmt"
"regexp"
)

func main() {
// 创建正则
re := regexp.MustCompile(`pattern`)

// 测试
re.MatchString(string) // 返回 bool
re.Match([]byte) // 返回 bool

// 查找
re.FindString(string) // 返回第一个匹配或空字符串
re.FindAllString(string, n) // 返回所有匹配(n=-1 表示所有)
re.FindStringSubmatch(string) // 返回分组匹配

// 替换
re.ReplaceAllString(string, replacement)
re.ReplaceAllStringFunc(string, func(string) string)

// 分割
re.Split(string, n)
}

性能优化建议

1. 避免回溯灾难

// 坏:重叠量词导致指数级回叩
/(a+)+b/.test("aaaaaaaaaaaaaaaaaaaaaaaaaaaa!");

// 好:使用具体的字符类
/a+b/.test("aaaaaaaaaaaaaaaaaaaaaaaaaaaa!");

2. 使用具体的字符类

// 较慢
/.*?/

// 较快
/[^\n]*?/

3. 预编译模式

import re

# 坏:每次都重新编译
for text in texts:
re.match(r"\d+", text)

# 好:预先编译
pattern = re.compile(r"\d+")
for text in texts:
pattern.match(text)

4. 使用锚点限制搜索范围

// 如果确知模式在开始位置
/^\d+/.exec(str); // 比 /\d+/ 更快

调试工具

  • RegExr - 在线正则表达式测试和学习工具
  • Regex101 - 支持多种引擎的正则表达式测试
  • Debuggex - 可视化正则表达式执行过程
  • RegexPal - 简洁的正则表达式测试工具

常见错误

错误原因解决
. 不匹配换行默认行为使用 [\s\S]s 标志
*+ 过度匹配贪婪匹配使用非贪婪量词 *? +?
特殊字符未转义$ * 等有特殊含义使用 \ 转义
字符类中 - 的位置- 在中间表示范围- 放在开头或结尾
Unicode 字符问题\w 等不匹配中文使用 \p{Han} 或 Unicode 范围

学习资源