正则快速参考
正则表达式是一种强大的模式匹配语言,几乎在所有编程语言中都可使用。本速查表侧重于实用而非理论。
核心语法
锚点
| 模式 | 匹配 |
|---|---|
^ |
字符串开头(多行模式下为行开头) |
$ |
字符串结尾(多行模式下为行结尾) |
\b |
单词边界 |
\B |
非单词边界 |
/^hello/.test('hello world') // true - 以 hello 开头
/world$/.test('hello world') // true - 以 world 结尾
/\bword\b/.test('password') // false - word 不是独立单词
/\bword\b/.test('a word here') // true
字符类
| 模式 | 匹配 |
|---|---|
. |
除换行符外的任意字符 |
\d |
数字 [0-9] |
\D |
非数字 |
\w |
单词字符 [a-zA-Z0-9_] |
\W |
非单词字符 |
\s |
空白字符(空格、制表符、换行) |
\S |
非空白字符 |
[abc] |
a、b 或 c |
[^abc] |
除 a、b、c 外的任意字符 |
[a-z] |
任意小写字母 |
[a-zA-Z0-9] |
字母数字 |
量词
| 模式 | 含义 |
|---|---|
* |
0 次或多次 |
+ |
1 次或多次 |
? |
0 次或 1 次(可选) |
{n} |
恰好 n 次 |
{n,} |
至少 n 次 |
{n,m} |
n 到 m 次 |
*? |
0 次或多次(懒惰/非贪婪) |
+? |
1 次或多次(懒惰) |
贪婪 vs 懒惰:
'<b>bold</b>'.match(/<.+>/)[0] // '<b>bold</b>' — 贪婪(尽可能多取)
'<b>bold</b>'.match(/<.+?>/)[0] // '<b>' — 懒惰(尽可能少取)
分组与选择
| 模式 | 含义 |
|---|---|
(abc) |
捕获组 |
(?:abc) |
非捕获组 |
(?<name>abc) |
命名捕获组 |
| `a | b` |
const match = '2026-05-28'.match(/(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/);
match.groups.year // '2026'
match.groups.month // '05'
match.groups.day // '28'
环视(零宽断言)
| 模式 | 含义 |
|---|---|
(?=...) |
正向先行断言 — 后面跟着 |
(?!...) |
负向先行断言 — 后面不跟着 |
(?<=...) |
正向后行断言 — 前面是 |
(?<!...) |
负向后行断言 — 前面不是 |
// 查找后面跟着 'px' 的数字
'10px 20em 30px'.match(/\d+(?=px)/g) // ['10', '30']
// 查找后面不跟着 'px' 的数字
'10px 20em 30px'.match(/\d+(?!px)\d*/g) // ['20']
// 不带货币符号的价格
'$100'.match(/(?<=\$)\d+/)[0] // '100'
标志
| 标志 | 效果 |
|---|---|
g |
全局 — 查找所有匹配 |
i |
不区分大小写 |
m |
多行 — ^ 和 $ 匹配行边界 |
s |
点号通配 — . 匹配换行符 |
u |
Unicode 模式 |
d |
生成子串索引(ES2022) |
20+ 个即用模式
邮箱地址
const emailRegex = /^[a-zA-Z0-9._%+\-]+@[a-zA-Z0-9.\-]+\.[a-zA-Z]{2,}$/;
emailRegex.test('user@example.com') // true
emailRegex.test('user+tag@sub.co.uk') // true
emailRegex.test('not-an-email') // false
URL
const urlRegex = /https?:\/\/(www\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_+.~#?&/=]*)/;
IPv4 地址
const ipv4 = /^((25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(25[0-5]|2[0-4]\d|[01]?\d\d?)$/;
ipv4.test('192.168.1.1') // true
ipv4.test('999.0.0.1') // false
强密码(8位以上,含大写、小写、数字、特殊字符)
const strongPassword = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[!@#$%^&*]).{8,}$/;
日期(YYYY-MM-DD)
const isoDate = /^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])$/;
电话号码(美国)
const usPhone = /^(\+1\s?)?\(?\d{3}\)?[\s.\-]?\d{3}[\s.\-]?\d{4}$/;
信用卡号
const creditCard = /^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|3[47][0-9]{13}|6(?:011|5[0-9]{2})[0-9]{12})$/;
十六进制颜色代码
const hexColor = /^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/;
hexColor.test('#fff') // true
hexColor.test('#3a9f2e') // true
hexColor.test('#gggggg') // false
Slug(URL 安全字符串)
const slug = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
slug.test('my-article-title') // true
slug.test('my_article') // false
从文本中提取所有 URL
const text = 'Visit https://example.com or http://test.org for more.';
const urls = text.match(/https?:\/\/[^\s]+/g);
// ['https://example.com', 'http://test.org']
移除 HTML 标签
const html = '<p>Hello <b>World</b></p>';
html.replace(/<[^>]+>/g, ''); // 'Hello World'
去除空白
str.replace(/^\s+|\s+$/g, '') // 等同于 str.trim()
str.replace(/\s+/g, ' ') // 将多个空格合并为一个
从字符串中提取数字
'Price: $29.99, Qty: 3'.match(/\d+\.?\d*/g) // ['29.99', '3']
JavaScript 正则方法
// test() — 返回布尔值
/\d+/.test('abc123') // true
// match() — 返回匹配数组(或 null)
'hello world'.match(/\w+/g) // ['hello', 'world']
// replace() / replaceAll()
'foo bar foo'.replace(/foo/g, 'baz') // 'baz bar baz'
// split()
'a,b,,c'.split(/,+/) // ['a', 'b', 'c']
// exec() — 返回匹配及索引
const re = /\d+/g;
let m;
while ((m = re.exec('a1b22c333')) !== null) {
console.log(m[0], 'at', m.index);
}
常见问题
问:如何使正则表达式不区分大小写?
添加 i 标志:/pattern/i 或 new RegExp('pattern', 'i')。
问:为什么带有 g 标志的正则在重复调用时行为异常?
g 标志会在正则对象上维护 lastIndex 状态。如果重复使用同一个正则对象,exec() 会从上次结束的位置开始。要么每次创建新正则,要么重置 re.lastIndex = 0。
问:match() 和 matchAll() 有什么区别?
带 g 的 match() 返回所有匹配,但不包含捕获组。matchAll() 返回一个迭代器,包含所有匹配对象及捕获组。
const str = 'test1 test2';
[...str.matchAll(/test(\d)/g)].map(m => m[1]) // ['1', '2']
→ 使用 Regex Tester 实时测试和调试你的正则模式。