每次写正则都要查半天,好不容易写出来过两天又忘了。这次系统地整理一遍,把最常用的模式记下来。
基础语法速查
js
const str = 'Hello 2026, my email is test@example.com'
// 字符匹配
/Hello/.test(str) // true --- 包含 "Hello"
/[0-9]/.test(str) // true --- 包含数字
/\d+/.exec(str) // ["2026"] --- \d 是 [0-9],+ 是一个或多个
// 常用简写
// \d = [0-9] \D = [^0-9]
// \w = [a-zA-Z0-9_] \W = 非 \w
// \s = 空格/Tab/换行 \S = 非空白
// . = 除换行外的任意字符
量词
js
/a*/ // 0 个或多个 a
/a+/ // 1 个或多个 a
/a?/ // 0 个或 1 个 a
/a{3}/ // 恰好 3 个 a
/a{2,5}/ // 2 到 5 个 a
/a{2,}/ // 至少 2 个 a
贪婪 vs 非贪婪:
js
const html = '<b>hello</b> and <i>world</i>'
// 贪婪(默认):匹配到最后一个 >
html.match(/<.*>/) // ["<b>hello</b> and <i>world</i>"]
// 非贪婪(加 ?):匹配到第一个 >
html.match(/<.*?>/g) // ["<b>", "</b>", "<i>", "</i>"]
分组和捕获
js
const date = '2026-09-17'
const match = date.match(/(\d{4})-(\d{2})-(\d{2})/)
match[0] // "2026-09-17" --- 完整匹配
match[1] // "2026" --- 第一个分组
match[2] // "09" --- 第二个分组
match[3] // "17" --- 第三个分组
// 命名分组(ES2018)
const named = date.match(/(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/)
named.groups.year // "2026"
named.groups.month // "09"
常用实战模式
js
// 手机号(中国大陆)
/^1[3-9]\d{9}$/
// 邮箱(简化版,够用)
/^[\w.-]+@[\w.-]+\.\w+$/
// URL
/^https?:\/\/[\w.-]+(?:\/[\w./?%&=-]*)?$/
// 身份证号
/^\d{17}[\dXx]$/
// 中文字符
/[\u4e00-\u9fa5]+/
// 去除首尾空白
str.replace(/^\s+|\s+$/g, '')
// 其实 str.trim() 就行,但面试可能让你手写
// 驼峰转短横线
'backgroundColor'.replace(/[A-Z]/g, m => '-' + m.toLowerCase())
// "background-color"
// 千分位逗号
'1234567890'.replace(/\B(?=(\d{3})+(?!\d))/g, ',')
// "1,234,567,890"
replace 的高级用法
js
// 回调函数可以拿到分组
'John Smith'.replace(/(\w+)\s(\w+)/, (match, first, last) => {
return `${last}, ${first}`
})
// "Smith, John"
// 用 $1, $2 引用分组
'2026-09-17'.replace(/(\d{4})-(\d{2})-(\d{2})/, '$2/$3/$1')
// "09/17/2026"
// lookahead(断言)
'abc123def'.replace(/\d+(?=[a-z])/, '***')
// "abc***def" --- 只匹配后面跟着字母的数字
// lookbehind(ES2018)
'price: 100'.replace(/(?<=price:\s)\d+/, '200')
// "price: 200" --- 只替换 price: 后面的数字
各语言的正则差异
| 特性 | JS | Python | Java |
|---|---|---|---|
| 字面量语法 | /pattern/flags |
re.compile(r'pattern') |
Pattern.compile("pattern") |
| 命名分组 | (?<name>...) |
(?P<name>...) |
(?<name>...) |
| lookbehind | ES2018 支持 | 支持 | 支持 |
| Unicode 属性 | \p{Script=Han} (ES2018) |
re.UNICODE |
\p{IsHan} |
调试工具
推荐 regex101.com,实时匹配 + 解释每个符号的含义。写复杂正则的时候开着它,省得反复跑代码测试。
总结
正则不需要背,记住 \d \w \s 三个简写、* + ? {n,m} 四个量词、() 分组、^ $ 边界,就够覆盖 80% 的场景。剩下的查文档或者 regex101。