Abstract
这篇笔记只整理“绝大部分开发里常用的正则表达式知识”。 目标不是覆盖所有冷门语法,而是让你能看懂、会写、会改常见正则。
一句话理解正则表达式
正则表达式,就是一种描述字符串模式的规则。
你可以用它来做这些事:
- 判断一段字符串是否符合某种格式。
- 从一段字符串中提取某些部分。
- 把匹配到的内容替换掉。
- 按某种规则拆分字符串。
在 JavaScript 里,它经常配合这些方法一起出现:
test()exec()match()matchAll()replace()split()search()
二、最常见的写法
正则通常有两种写法:
/abc/
new RegExp("abc")日常开发里更常见的是第一种字面量写法。
例如:
/hello/表示:匹配字符串里是否出现 hello。
三、最常用的基础语法
1. 普通字符
普通字符就表示它自己。
/abc/表示匹配 abc。
2. 字符类 []
表示“匹配方括号中的任意一个字符”。
/[abc]/表示匹配:
abc
例如:
/[abc]/.test("cat") // true常见写法
/[0-9]/ // 任意一位数字
/[a-z]/ // 任意一个小写字母
/[A-Z]/ // 任意一个大写字母
/[a-zA-Z]/ // 任意一个英文字母
/[a-zA-Z0-9]/ // 任意一个字母或数字3. 取反字符类 [^]
在方括号里,^ 放在最前面时,表示“不要这些字符”。
/[^0-9]/表示匹配任意一个“非数字”字符。
4. 预定义字符类
这是最常用的一组缩写。
| 写法 | 含义 |
|---|---|
\d | 任意一个数字,等价于 [0-9] |
\D | 任意一个非数字 |
\w | 任意一个字母、数字、下划线,约等于 [A-Za-z0-9_] |
\W | 任意一个非“字母数字下划线”字符 |
\s | 任意一个空白字符,如空格、换行、制表符 |
\S | 任意一个非空白字符 |
. | 任意一个字符,通常不包含换行 |
例子:
/\d\d/.test("12") // true
/\w+/.test("hello_123") // true
/\s/.test("a b") // trueTip
.很常用,但也最容易误伤。 它表示“几乎任意字符”,所以写宽了很容易匹配过头。
四、量词:匹配多少次
量词是正则里非常核心的一部分。
1. 常见量词
| 写法 | 含义 |
|---|---|
* | 前面的内容出现 0 次或多次 |
+ | 前面的内容出现 1 次或多次 |
? | 前面的内容出现 0 次或 1 次 |
{n} | 前面的内容恰好出现 n 次 |
{n,} | 前面的内容至少出现 n 次 |
{n,m} | 前面的内容出现 n 到 m 次 |
例子:
/a*/ // "", "a", "aa", "aaa"
/a+/ // "a", "aa", "aaa"
/a?/ // "", "a"
/\d{3}/ // 恰好 3 位数字
/\d{6,}/ // 至少 6 位数字2. 贪婪模式与非贪婪模式
默认情况下,量词是贪婪的,也就是“能吃多少吃多少”。
/".+"/这种思路会尽可能多地匹配。
更常见的写法是加 ? 变成非贪婪:
/".+?"/例子:
const str = 'a "one" b "two"'
str.match(/".+"/) // 可能吃到 "one" b "two"
str.match(/".+?"/) // 只匹配到 "one"Warning
很多“正则匹配太多了”的问题,本质就是贪婪匹配导致的。
五、边界:匹配在什么位置
边界不匹配字符本身,而是匹配“位置”。
1. 开头和结尾
| 写法 | 含义 |
|---|---|
^ | 字符串开头 |
$ | 字符串结尾 |
例子:
/^abc/ // 以 abc 开头
/abc$/ // 以 abc 结尾
/^abc$/ // 整个字符串必须就是 abc这组非常重要。
比如你想验证“整个输入是否为 11 位数字”,就不能只写:
/\d{11}/因为这只是“字符串里出现了 11 位数字”。
而更准确的是:
/^\d{11}$/表示整段字符串从头到尾都必须是 11 位数字。
2. 单词边界
| 写法 | 含义 |
|---|---|
\b | 单词边界 |
\B | 非单词边界 |
例如:
/\bcat\b/表示匹配独立的 cat,而不是 catalog 里的 cat。
六、分组与或
1. 分组 ()
圆括号有两个最常见用途:
- 把多个内容当成一个整体。
- 捕获匹配到的内容。
例如:
/(ab)+/表示 ab 这个整体出现一次或多次。
2. 或 |
表示“二选一”。
/cat|dog/表示匹配 cat 或 dog。
如果要和分组配合:
/gr(a|e)y/表示匹配:
graygrey
3. 捕获组
括号默认会捕获内容。
/(\d{4})-(\d{2})-(\d{2})/如果匹配 2026-05-07,就能把年、月、日分别抓出来。
const result = "2026-05-07".match(/(\d{4})-(\d{2})-(\d{2})/)常见结果:
- 第 0 项:完整匹配
- 第 1 项:第一组
- 第 2 项:第二组
- 第 3 项:第三组
4. 非捕获组 (?:)
如果你只想分组,不想捕获,可以用:
/(?:ab)+/这在结构复杂一点的正则里很有用。
七、常用断言
断言的特点是:它只判断位置条件,不真正消费字符。
日常最常用的是下面四种。
1. 正向先行断言 (?=...)
表示:后面必须跟着某内容。
/\d(?=px)/表示匹配后面紧跟 px 的数字。
例如在 12px 中,可以匹配到 2 这个位置上的数字。
2. 负向先行断言 (?!...)
表示:后面不能跟着某内容。
/\d(?!px)/3. 正向后行断言 (?<=...)
表示:前面必须是某内容。
/(?<=\$)\d+/表示匹配 $100 里的 100。
4. 负向后行断言 (?<!...)
表示:前面不能是某内容。
/(?<!\$)\d+/Note
断言在“提取某一部分内容,但不想把前后标记也带上”时特别好用。
八、常用修饰符
修饰符写在正则最后面。
/abc/g最常用的是这些:
| 修饰符 | 含义 |
|---|---|
g | 全局匹配 |
i | 忽略大小写 |
m | 多行模式 |
s | 让 . 也能匹配换行 |
1. g
如果不加 g,通常只拿到第一个匹配。
"a1b2c3".match(/\d/) // 只拿第一个
"a1b2c3".match(/\d/g) // 拿到全部2. i
忽略大小写。
/abc/i可以匹配 abc、ABC、Abc。
3. m
让 ^ 和 $ 针对每一行生效,而不是只针对整个字符串的头尾。
4. s
让 . 能匹配换行。
这个在处理多行文本时很有用。
九、转义:什么时候要加反斜杠
有些字符在正则里有特殊含义,如果你想匹配它本身,就要转义。
常见需要转义的字符有:
. * + ? ^ $ { } ( ) [ ] \ | /例如匹配点号 .:
/\./匹配左括号:
/\(/匹配网址里的 https:// 时,也常常会遇到转义问题。
十、JavaScript 里最常用的几个方法
1. test()
只关心“符不符合”时最常用。
/^\d+$/.test("123") // true2. exec()
适合拿更详细的匹配结果。
/\d+/.exec("abc123def")3. match()
字符串方法。
"abc123def".match(/\d+/)4. replace()
特别常用。
"2026-05-07".replace(/-/g, "/")5. split()
按某个模式拆分字符串。
"a, b; c".split(/[;,]\s*/)十一、最常见的实战例子
这里只放最常用、最有代表性的。
1. 匹配纯数字
/^\d+$/2. 匹配字母和数字
/^[A-Za-z0-9]+$/3. 匹配字母、数字、下划线
/^\w+$/4. 匹配 6 到 18 位密码
/^[A-Za-z0-9_]{6,18}$/5. 匹配 11 位手机号(简单版)
/^1\d{10}$/Warning
像手机号、邮箱这类格式,正则通常只能做“基本校验”。 真正严谨的业务校验,往往还需要额外规则。
6. 匹配邮箱(常用简化版)
/^[^\s@]+@[^\s@]+\.[^\s@]+$/7. 匹配 URL(简单版)
/^https?:\/\/[^\s/$.?#].[^\s]*$/i这个可以和 URL 一起理解。
8. 提取日期
/(\d{4})-(\d{2})-(\d{2})/适合提取这种格式:
2026-05-079. 去掉首尾空格
/^\s+|\s+$/g当然在 JavaScript 里更推荐直接用:
str.trim()10. 把多个空白合成一个空格
/\s+/g11. 提取标签内容时的基础思路
/<[^>]+>/但这里一定要注意:
Danger
不要把正则当成完整解析 HTML 的工具。 处理 HTML 结构,更应该使用 DOM 或解析器。
十二、写正则时的实用思路
如果你觉得正则难写,通常不是语法问题,而是没有拆解问题。
更好的写法是:
- 先确认要匹配的是“整段”,还是“其中一部分”。
- 再确认是否需要
^和$。 - 再拆成一个个小块。
- 最后再加量词、分组、断言。
比如“11 位手机号”可以拆成:
- 整段都要匹配,所以加
^和$ - 第一位必须是
1 - 后面再跟 10 位数字
最后得到:
/^1\d{10}$/十三、初学者最容易犯的错
1. 忘了加 ^ 和 $
这是最常见的问题之一。
/\d{6}/和
/^\d{6}$/含义完全不同。
前者表示“包含 6 位数字”,后者表示“整个字符串就是 6 位数字”。
2. . 用太多
/.+/很容易写得过宽。
3. 贪婪匹配导致吃太多
尤其是在配合 .*、.+ 时最常见。
4. 过度追求“一条正则解决一切”
很多时候,把逻辑拆成两步写,会比一条超复杂正则更清晰、更可维护。
十四、够用的学习顺序
如果你只想掌握大部分常用正则,建议按这个顺序:
- 普通字符
- 字符类
[] - 预定义字符类
\d\w\s - 量词
* + ? {n,m} - 边界
^ $ - 分组
()和| - 常见方法
test/match/replace - 断言
把这些学会,已经能覆盖大多数日常开发场景。
十五、最值得记住的几个模板
/^\d+$/ // 纯数字
/^[A-Za-z]+$/ // 纯字母
/^\w+$/ // 字母数字下划线
/^\d{4}-\d{2}-\d{2}$/ // 日期 yyyy-mm-dd
/^1\d{10}$/ // 中国大陆手机号简化版
/^[^\s@]+@[^\s@]+\.[^\s@]+$/ // 邮箱简化版
/\s+/g // 连续空白
/^\s+|\s+$/g // 首尾空白