正则表达式基础入门教程 2026 | 零基础小白学 Regex

看到 /^[a-zA-Z0-9]+@[a-zA-Z0-9.]+$/ 这种像乱码一样的字符串就头大?别怕!正则表达式其实就是一种「描述文本模式的迷你语言」。这篇教程用大白话带你从零掌握它。
一、正则表达式是什么?
1.1 通俗理解
想象你是一个图书管理员,要在书架上找出「所有以张开头、以明结尾的三个字的人名」。你描述给助手听的就是一种「模式」。
正则表达式(Regular Expression,简称 Regex 或 RegExp)就是干这个的:用一串特殊符号描述「我要找什么样的文本」,然后计算机帮你把符合的都找出来。
1.2 能用来干什么?
| 场景 | 例子 |
|---|---|
| 表单验证 | 这个字符串是不是合法邮箱?手机号? |
| 文本搜索 | 在一篇文章里找出所有 URL 链接 |
| 文本替换 | 把文章里所有「color」替换成「colour」 |
| 数据提取 | 从日志里提取所有 IP 地址 |
| 字符串拆分 | 按任意空白符分割句子 |
1.3 生活中的正则
- 在 Word 里「查找替换」用通配符
?* - 在终端用
ls *.md列出所有 markdown 文件 - 在 SQL 里用
LIKE '张%'
正则就是这些「通配符」的超级加强版。
二、在 JavaScript 里怎么用?
2.1 两种创建方式
// 方式一:字面量(推荐,简洁)
const re1 = /hello/g
// 方式二:构造函数(适合动态拼接)
const word = 'hello'
const re2 = new RegExp(word, 'g')2.2 两个核心方法
// 1. test():判断字符串是否匹配(返回 true/false)
const re = /\d{4}/ // 匹配 4 位数字
console.log(re.test('订单号 2026')) // true
console.log(re.test('没有数字')) // false
// 2. match():取出匹配到的内容
const str = '我的手机是 13812345678,邮箱是 a@b.com'
console.log(str.match(/\d{11}/)) // ['13812345678']2.3 常用方法速查
| 方法 | 作用 | 返回值 |
|---|---|---|
re.test(str) | 是否匹配 | true / false |
str.match(re) | 提取匹配 | 数组或 null |
str.matchAll(re) | 提取所有匹配 | 迭代器 |
str.replace(re, 新) | 替换 | 新字符串 |
str.split(re) | 按模式分割 | 数组 |
re.exec(str) | 详细匹配 | 数组(含位置) |
三、最基础:匹配普通字符
3.1 字面量匹配
最简单的正则,就是原样写你要找的字符:
const str = 'I love cats and cats are cute'
// 找出所有 'cats'
console.log(str.match(/cats/g))
// ['cats', 'cats']注意结尾的 g
/cats/g 末尾的 g 是「全局匹配」标志,不加的话只找第一个。
3.2 标志位(Flags)
| 标志 | 含义 | 例子 |
|---|---|---|
g | 全局(找全部) | /cat/g |
i | 忽略大小写 | /cat/i 匹配 Cat CAT |
m | 多行模式 | ^ $ 匹配每行首尾 |
s | 让 . 匹配换行符 | 跨行匹配 |
组合使用:/cat/gi = 全局 + 忽略大小写。
四、元字符:正则的「特殊符号」
元字符是正则里有特殊含义的符号,就像数学里的 + - × ÷。
4.1 速查表
| 符号 | 含义 | 例子 | 匹配 |
|---|---|---|---|
. | 任意一个字符(除换行) | a.c | abc a1c a@c |
\d | 一个数字(0-9) | \d\d | 42 |
\D | 非数字 | \D | a @ |
\w | 字母数字下划线 | \w+ | hello_123 |
\W | 非字母数字下划线 | \W | @ 空格 |
\s | 空白符(空格/制表/换行) | \s | |
\S | 非空白符 | \S | a 1 |
\b | 单词边界 | \bcat\b | 匹配独立的 cat |
\B | 非单词边界 | \Bcat | 匹配 concat 里的 cat |
4.2 记忆技巧
- 小写 = 「是这一类」(
\d是数字,\w是字母数字,\s是空白) - 大写 = 「不是这一类」(
\D非数字,\W非字母数字,\S非空白)
4.3 转义:想匹配符号本身
如果就想匹配 . * + 这些特殊符号本身,前面加 \:
// 想匹配网址里的点
'www.google.com'.match(/\./g) // ['.', '.']
// 想匹配价格里的美元符号
'$100'.match(/\$\d+/) // ['$100']需要转义的符号:. * + ? ^ $ { } [ ] \ | ( )
五、字符类:用方括号自定义范围
5.1 基本用法
用 [...] 表示「匹配其中任意一个字符」:
// 匹配 a、b、c 中任意一个
'banana'.match(/[abc]/g) // ['b', 'a', 'a', 'a']
// 匹配一个数字
'a1b2'.match(/[0123456789]/g) // ['1', '2']5.2 范围表示法
用 - 表示范围:
/[a-z]/ // 任意小写字母
/[A-Z]/ // 任意大写字母
/[0-9]/ // 任意数字(等价于 \d)
/[a-zA-Z]/ // 任意字母
/[a-zA-Z0-9_]/ // 字母数字下划线(等价于 \w)5.3 取反:[^...]
在开头加 ^ 表示「不要这些字符」:
// 匹配「非数字」
'abc123'.match(/[^0-9]/g) // ['a', 'b', 'c']
// 匹配「非元音字母」
'hello'.match(/[^aeiou]/g) // ['h', 'l', 'l']注意区分
^ 在 [] 内是「取反」,在 [] 外是「行首」,含义完全不同!
六、量词:指定重复次数
6.1 速查表
| 量词 | 含义 | 例子 | 匹配 |
|---|---|---|---|
* | 0 次或多次 | ab*c | ac abc abbc |
+ | 1 次或多次 | ab+c | abc abbc(不匹配 ac) |
? | 0 次或 1 次 | colou?r | color colour |
{n} | 正好 n 次 | \d{4} | 2026 |
{n,} | 至少 n 次 | \d{2,} | 12 123 1234 |
{n,m} | n 到 m 次 | \d{2,4} | 12 123 1234 |
6.2 实战例子
// 匹配手机号(11 位数字)
/^1\d{10}$/.test('13812345678') // true
// 匹配 4-6 位验证码
/^\d{4,6}$/.test('123456') // true
// 匹配 HTML 标签里的颜色(# 后 3 或 6 位)
'#fff'.match(/^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/) // 匹配6.3 贪婪 vs 非贪婪
默认正则是「贪婪」的,会尽可能多匹配。加 ? 变「非贪婪」(尽可能少匹配):
const str = '<div>hello</div>'
// 贪婪(默认):匹配到最远的 >
str.match(/<.*>/)[0] // '<div>hello</div>'
// 非贪婪:匹配到最近的 >
str.match(/<.*?>/)[0] // '<div>'记忆
量词后加 ? = 「别贪心,够了就行」。*? +? ?? {n,m}?
七、锚点:定位位置
7.1 三个常用锚点
| 符号 | 含义 | 例子 |
|---|---|---|
^ | 字符串开头 | ^Hello 匹配开头的 Hello |
$ | 字符串结尾 | world$ 匹配结尾的 world |
\b | 单词边界 | \bcat\b 匹配独立的单词 cat |
7.2 实战
// 必须是纯数字(从头到尾)
/^\d+$/.test('12345') // true
/^\d+$/.test('12a45') // false
// 以 https 开头
/^https:\/\//.test('https://example.com') // true
// 匹配独立单词 'is',不匹配 'this' 里的 'is'
'this is a test'.match(/\bis\b/g) // ['is']表单验证必备
做表单验证时,记得用 ^ 和 $ 包住整个模式,否则只匹配到一部分也会返回 true:
/\d+/对abc123返回 true(因为里面有数字)/^\d+$/对abc123返回 false(必须全是数字)
八、分组与引用
8.1 捕获分组 ()
用括号把一部分「打包」,可以整体应用量词或提取:
// 匹配 'ab' 重复 3 次
'ababab'.match(/(ab){3}/) // 匹配
// 提取日期中的年月日
const date = '2026-08-08'
const m = date.match(/(\d{4})-(\d{2})-(\d{2})/)
console.log(m[1]) // '2026' 年
console.log(m[2]) // '08' 月
console.log(m[3]) // '08' 日8.2 命名分组 (?<名字>)
const date = '2026-08-08'
const m = date.match(/(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/)
console.log(m.groups.year) // '2026'
console.log(m.groups.month) // '08'8.3 反向引用 \1
在正则里引用前面捕获到的内容:
// 匹配连续重复的单词
'hello hello world'.match(/\b(\w+)\s\1\b/) // 匹配 'hello hello'
// 匹配成对的引号
'"hello"'.match(/(['"]).*?\1/) // 匹配 '"hello"'(前后引号一致)8.4 非捕获分组 (?:...)
括号默认会「捕获」内容(占内存),如果只想分组不捕获,加 ?::
// 只想整体应用 ? 量词,不需要提取
'color colour'.match(/colou(?:r|rs?)/g)九、选择:或 |
用 | 表示「或」:
// 匹配 cat 或 dog
/cat|dog/.test('I have a dog') // true
// 匹配几种水果
/apple|banana|orange/.test('banana') // true
// 配合分组使用
/(jpg|png|gif)$/i.test('photo.JPG') // true(图片后缀)注意优先级
| 的优先级很低,cat|dog food 是「cat」或「dog food」。要「cat food 或 dog food」得写成 (cat|dog) food。
十、常用正则大全(直接抄)
10.1 邮箱
const emailRe = /^[\w.+-]+@[\w-]+(\.[\w-]+)+$/
emailRe.test('user@example.com') // true
emailRe.test('user.name+tag@site.co') // true
emailRe.test('invalid') // false10.2 手机号(中国大陆)
const phoneRe = /^1[3-9]\d{9}$/
phoneRe.test('13812345678') // true
phoneRe.test('12345678901') // false(第二位必须是 3-9)10.3 URL
const urlRe = /^https?:\/\/[\w.-]+(\.[\w.-]+)+[/\w\-./?%&=]*$/
urlRe.test('https://www.example.com/path?q=1') // true10.4 身份证号(18 位)
const idRe = /^\d{17}[\dXx]$/
idRe.test('110105199001011234') // true
idRe.test('11010519900101123X') // true10.5 IPv4 地址
const ipRe = /^((25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(25[0-5]|2[0-4]\d|[01]?\d\d?)$/
ipRe.test('192.168.1.1') // true
ipRe.test('256.1.1.1') // false10.6 密码强度(至少 8 位,含大小写字母和数字)
const pwdRe = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).{8,}$/
pwdRe.test('Abc12345') // true
pwdRe.test('abc12345') // false(缺大写)
pwdRe.test('Abc1') // false(太短)零宽断言
(?=...) 叫「正向先行断言」,表示「后面要跟着...」但不消耗字符。上面密码正则用三个断言确保「整个字符串里既有大写、又有小写、又有数字」。
10.7 中文字符
const cnRe = /[\u4e00-\u9fa5]+/
cnRe.test('你好world') // true
'你好world'.match(cnRe) // ['你好']10.8 提取网页所有链接
const html = '<a href="https://a.com">A</a> <a href="/b">B</a>'
const urls = html.match(/href="([^"]+)"/g)
// ['href="https://a.com"', 'href="/b"']十一、在表单验证中实战
11.1 一个完整的表单校验
<form id="myForm">
<div>
<label>邮箱</label>
<input type="text" id="email">
<span class="error" id="emailErr"></span>
</div>
<div>
<label>手机号</label>
<input type="text" id="phone">
<span class="error" id="phoneErr"></span>
</div>
<div>
<label>密码(8位以上含大小写和数字)</label>
<input type="password" id="pwd">
<span class="error" id="pwdErr"></span>
</div>
<button type="submit">提交</button>
</form>
<script>
const rules = {
email: /^[\w.+-]+@[\w-]+(\.[\w-]+)+$/,
phone: /^1[3-9]\d{9}$/,
pwd: /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).{8,}$/
}
const msgs = {
email: '邮箱格式不正确',
phone: '手机号格式不正确',
pwd: '密码需 8 位以上,含大小写字母和数字'
}
document.getElementById('myForm').addEventListener('submit', (e) => {
e.preventDefault()
let valid = true
for (const field of ['email', 'phone', 'pwd']) {
const value = document.getElementById(field).value
const errEl = document.getElementById(field + 'Err')
if (!rules[field].test(value)) {
errEl.textContent = msgs[field]
valid = false
} else {
errEl.textContent = ''
}
}
if (valid) {
alert('提交成功!')
}
})
</script>11.2 文本替换实战
// 把手机号中间 4 位替换成 ****
'13812345678'.replace(/(\d{3})\d{4}(\d{4})/, '$1****$2')
// '138****5678'
// 把文本里的 URL 变成链接
const text = '访问 https://example.com 看看'
text.replace(/(https?:\/\/[^\s]+)/g, '<a href="$1">$1</a>')
// '访问 <a href="https://example.com">https://example.com</a> 看看'
// 驼峰转下划线
'userName'.replace(/([A-Z])/g, '_$1').toLowerCase()
// 'user_name'十二、调试技巧
12.1 在线工具推荐
- regex101.com —— 最强在线测试,有详细解释
- regexr.com —— 适合学习,带速查表
12.2 浏览器里直接试
打开浏览器控制台(F12),直接敲:
/^\d{4}$/.test('2026') // true12.3 调试步骤
- 先把要匹配的样本数据列出来
- 在 regex101 里粘贴样本
- 逐步写正则,每写一段看高亮是否正确
- 加入边界测试(该匹配的、不该匹配的都试)
- 复制到代码里使用
12.4 常见调试坑
// 坑:忘了 ^ $,部分匹配也算对
/\d{11}/.test('abc13812345678xyz') // true(里面有 11 位数字)
/^\d{11}$/.test('abc13812345678xyz') // false(必须是纯 11 位)
// 坑:忘了 g 标志,replace 只换第一个
'aabb'.replace(/a/, 'X') // 'Xabb'
'aabb'.replace(/a/g, 'X') // 'XXbb'十三、练习题
基础题
- 写一个正则,匹配任意 3 位数字 →
/\d{3}/ - 写一个正则,匹配以
http开头的字符串 →/^http/ - 写一个正则,匹配包含「cat」或「dog」的句子 →
/cat|dog/
进阶题
- 写一个正则,匹配 6-16 位由字母和数字组成的密码
- 写一个正则,提取字符串里所有的邮箱地址
- 写一个正则,把日期
2026/08/08转成2026-08-08
参考答案
// 题 4
/^[a-zA-Z0-9]{6,16}$/
// 题 5
const text = '联系 a@b.com 或 c@d.com'
text.match(/[\w.+-]+@[\w-]+(\.[\w-]+)+/g)
// ['a@b.com', 'c@d.com']
// 题 6
'2026/08/08'.replace(/\//g, '-') // '2026-08-08'十四、正则速查卡(收藏)
基础:
. 任意字符
\d \D 数字 / 非数字
\w \W 字母数字下划线 / 非字母数字下划线
\s \S 空白 / 非空白
\b \B 单词边界 / 非边界
字符类:
[abc] a 或 b 或 c
[a-z] a 到 z
[^abc] 非 a、b、c
量词:
* 0 次或多次
+ 1 次或多次
? 0 次或 1 次
{n} 正好 n 次
{n,} 至少 n 次
{n,m} n 到 m 次
*? +? ?? 非贪婪版本
锚点:
^ 开头
$ 结尾
分组:
(...) 捕获分组
(?:...) 非捕获分组
(?<name>...) 命名分组
\1 \2 反向引用
选择:
| 或
标志:
g 全局
i 忽略大小写
m 多行
s . 匹配换行
零宽断言:
(?=...) 后面跟着
(?!...) 后面不跟着
(?<=...) 前面是
(?<!...) 前面不是总结
正则表达式的学习路线:
- 认识工具:知道
test()match()replace()怎么用 - 掌握元字符:
. \d \w \s \b这些基础符号 - 学会量词:
* + ? {n,m}控制重复 - 会用字符类:
[a-z][^0-9]自定义范围 - 理解分组:
()打包、提取、引用 - 记常用模板:邮箱、手机号、URL 这些直接抄
- 多练多查:用 regex101 边写边测
学习建议
不用死记硬背!记住「正则能干什么」,具体语法用的时候查速查卡就行。写多了自然就熟了。
正则是程序员的「瑞士军刀」,虽然看起来像乱码,但掌握后你会发现它无比强大。遇到文本处理问题,第一反应就会变成:「这个能用正则解决吗?」
下一步建议结合 JavaScript 基础入门教程 里的字符串处理章节一起练习,效果更好。