正则表达式入门到精通
正则表达式(Regular Expression,简称regex)是处理文本的强大工具。无论是数据验证、文本提取还是字符串替换,正则表达式都能高效完成。本文从基础语法到高级技巧,帮助你全面掌握正则表达式。
基础语法
字面量字符
最简单的正则就是匹配字面量字符:
/hello/.test('hello world') // true
/world/.test('hello world') // true
元字符
| 元字符 | 含义 | 示例 |
|---|---|---|
. |
匹配任意字符(除换行) | a.c 匹配 “abc”、“a1c” |
\d |
匹配数字 [0-9] | \d+ 匹配 “123” |
\w |
匹配单词字符 [a-zA-Z0-9_] | \w+ 匹配 “hello_123” |
\s |
匹配空白字符 | \s+ 匹配空格、制表符 |
\b |
匹配单词边界 | \bword\b 匹配独立的 “word” |
^ |
匹配字符串开头 | ^Hello 匹配以Hello开头 |
$ |
匹配字符串结尾 | world$ 匹配以world结尾 |
量词
| 量词 | 含义 | 示例 |
|---|---|---|
* |
0次或多次 | ab* 匹配 “a”、“ab”、“abb” |
+ |
1次或多次 | ab+ 匹配 “ab”、“abb”,不匹配 “a” |
? |
0次或1次 | colou?r 匹配 “color” 和 “colour” |
{n} |
恰好n次 | \d{3} 匹配三位数字 |
{n,m} |
n到m次 | \d{2,4} 匹配2到4位数字 |
字符类
方括号[]定义字符类,匹配其中任意一个字符:
/[aeiou]/ // 匹配任意元音字母
/[a-z]/ // 匹配任意小写字母
/[A-Za-z0-9]/ // 匹配任意字母或数字
/[^abc]/ // 匹配除a、b、c以外的字符(取反)
分组与捕获
捕获组
圆括号()创建捕获组,可以提取匹配的子串:
const match = '2026-05-28'.match(/(\d{4})-(\d{2})-(\d{2})/)
console.log(match[1]) // "2026"(年)
console.log(match[2]) // "05"(月)
console.log(match[3]) // "28"(日)
非捕获组
(?:)创建非捕获组,只分组不捕获:
/h(?:ello|i) world/ // 匹配 "hello world" 或 "hi world"
命名捕获组
ES2018支持命名捕获组,更易读:
const match = '2026-05-28'.match(/(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/)
console.log(match.groups.year) // "2026"
console.log(match.groups.month) // "05"
常用正则模式
邮箱验证
const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/
emailRegex.test('user@example.com') // true
emailRegex.test('invalid-email') // false
手机号验证(中国大陆)
const phoneRegex = /^1[3-9]\d{9}$/
phoneRegex.test('13812345678') // true
phoneRegex.test('12345678901') // false
URL验证
const urlRegex = /^https?:\/\/(www\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_+.~#?&//=]*)$/
urlRegex.test('https://example.com/path?q=1') // true
身份证号验证(中国大陆)
const idCardRegex = /^\d{17}[\dXx]$/
idCardRegex.test('110101199003074518') // true(简化版验证)
HTML标签提取
const tagRegex = /<([a-z]+)[^>]*>(.*?)<\/\1>/gi
'<b>bold</b> and <i>italic</i>'.match(tagRegex)
// ["<b>bold</b>", "<i>italic</i>"]
常用操作
字符串替换
// 替换所有空格为连字符
'hello world foo'.replace(/\s+/g, '-') // "hello-world-foo"
// 驼峰命名转换
'background-color'.replace(/-([a-z])/g, (_, c) => c.toUpperCase())
// "backgroundColor"
// 去除首尾空格
' hello '.replace(/^\s+|\s+$/g, '') // "hello"
字符串分割
// 按多种分隔符分割
'a,b;c d|e'.split(/[,;|\s]+/) // ["a", "b", "c", "d", "e"]
提取所有匹配
// 提取所有数字
'abc123def456'.match(/\d+/g) // ["123", "456"]
// 提取所有链接
const html = '<a href="https://a.com">A</a><a href="https://b.com">B</a>'
html.match(/href="([^"]+)"/g) // ["href=\"https://a.com\"", "href=\"https://b.com\""]
高级技巧
零宽断言
// 前瞻断言:匹配后面跟着特定内容的位置
'hello123world'.match(/\d+(?=world)/) // "123"
// 后顾断言:匹配前面有特定内容的位置
'$100 €200'.match(/(?<=\$)\d+/) // "100"
// 负前瞻:匹配后面不跟特定内容的位置
'hello123world456foo'.match(/\d+(?!world)/) // "456"
贪婪与非贪婪
默认量词是贪婪的(尽可能多匹配),加?变为非贪婪:
// 贪婪匹配
'<div>hello</div><div>world</div>'.match(/<div>.*<\/div>/)
// ["<div>hello</div><div>world</div>"]
// 非贪婪匹配
'<div>hello</div><div>world</div>'.match(/<div>.*?<\/div>/)
// ["<div>hello</div>"]
标志位
| 标志 | 含义 |
|---|---|
g |
全局匹配(匹配所有结果) |
i |
忽略大小写 |
m |
多行模式(^和$匹配每行) |
s |
dotAll模式(.匹配换行符) |
u |
Unicode模式 |
调试技巧
- 分步构建 — 复杂正则拆分为多个简单部分逐步测试
- 使用在线工具 — regex101.com 可视化正则匹配过程
- 添加注释 — 复杂正则使用
x模式(忽略空白)添加注释 - 避免灾难性回溯 — 嵌套量词
(a+)+可能导致性能问题
总结
正则表达式是文本处理的瑞士军刀。掌握基础语法后,通过大量实践积累常用模式,就能在开发中高效处理各种文本匹配需求。记住:好的正则应该简洁明了,过于复杂的正则难以维护。