从零开始,掌握正则表达式的核心语法与应用,轻松应对文本匹配、验证、替换等场景。
一、什么是正则表达式?
正则表达式 (简称 regex)是一种用于匹配字符串中字符组合的模式。它可以用来检查一个字符串是否包含某个子串、替换匹配的文本、或者从字符串中提取符合条件的信息。
在 JavaScript 中,正则表达式是一个对象,支持多种方法(如 test、exec、match、replace 等)。
创建正则表达式(两种方式)
1. 字面量形式(推荐)
性能更优,适合规则固定的场景,语法简洁直观,编译效率更高
javascript
const reg = /前端/;
2. 构造函数形式
适合规则动态生成、需要传入变量的场景,灵活性更强,可动态拼接匹配规则
javascript
const keyWord = '前端';
const reg = new RegExp(keyWord);
常用方法
| 方法 | 所属对象 | 作用 | 示例 |
|---|---|---|---|
| test(str) | 正则对象 | 检测字符串是否匹配规则,返回布尔值 | /前端/.test('学前端') → true |
| exec(str) | 正则对象 | 执行匹配,返回第一个匹配结果数组(含详细信息),无匹配则返回null | /前端/.exec('学前端,学正则') → ['前端'] |
| match(reg) | 字符串 | 提取匹配内容,配合g修饰符可返回所有匹配结果 | '学前端,学正则'.match(/学/g) → ['学', '学'] |
| replace(reg, replacement) | 字符串 | 替换匹配的文本内容,支持分组引用 | '学java'.replace(/java/, '前端') → '学前端' |
二、正则表达式核心语法
1. 修饰符:定义匹配行为
修饰符写在正则末尾,控制匹配的全局、大小写、多行等规则,是正则的 "辅助规则",决定匹配的范围和方式。
| 修饰符 | 全称 | 作用 | 示例 |
|---|---|---|---|
| g | global | 全局匹配,查找所有符合规则的内容,而非只找第一个 | /a/g 匹配字符串中所有字母a |
| i | ignore | 忽略大小写,不区分字母大小写匹配 | /hello/i 可匹配Hello、HELLO、hello |
| m | multi-line | 多行匹配,改变^和$的匹配范围,使其匹配每行的开头和结尾 | 适用于多行文本的逐行校验 |
2. 元字符:正则的核心特殊符号
元字符是具有特殊含义的符号,它们让正则表达式拥有强大的功能。
2.1 边界符
| 边界符 | 说明 | 示例 |
|---|---|---|
| ^ | 匹配字符串的开头 | /^a/ 匹配以字母a开头的字符串 |
| $ | 匹配字符串的结尾 | /a$/ 匹配以字母a结尾的字符串 |
| \b | 单词边界(单词与非单词的衔接位置) | /\bcat\b/ 匹配独立单词cat,不匹配category、scattered |
精准匹配示例:
javascript
// 精确匹配单个字符a,开头结尾都是a,中间无其他字符
/^a$/.test('a'); // true
/^a$/.test('aa'); // false
2.2 量词:限定字符出现的次数
用于指定字符或组出现的次数,解决 "重复匹配" 问题。
| 量词 | 作用 | 示例 |
|---|---|---|
| * | 匹配0 次或多次(可有可无) | /a*/ 匹配空字符串、a、aa、aaa |
| + | 匹配1 次或多次(至少 1 次) | /a+/ 匹配a、aa,不匹配空字符串 |
| ? | 匹配0 次或 1 次(最多 1 次) | /a?/ 匹配空字符串、a,不匹配aa |
| { n } | 恰好匹配 n 次 | /a{3}/ 只能匹配aaa |
| { n, } | 至少匹配 n 次 | /a{2,}/ 匹配aa、aaa及以上 |
| { n,m } | 匹配n~m次(包含 n、m) | /a{2,4}/ 匹配aa、aaa、aaaa |
量词示例:
javascript
/^a*$/.test(''); // true
/^a+$/.test(''); // false
/^a{3}$/.test('aaa'); // true
2.3 字符类:匹配指定范围内的字符
用[ ]包裹,匹配括号内任意一个字符,支持范围书写,大幅简化规则编写,无需逐个罗列字符。
- 基础字符类:[abc] 匹配a、b、c其中一个
- 范围字符类:
-
a-z\]:任意小写字母
-
0-9\]:任意数字
- 取反字符类:[^] 匹配除了括号内的字符
-
\^a-z\]:匹配非小写字母的所有字符
简写形式:
| 预定义类 | 作用 | 等价写法 |
|---|---|---|
| \d | 匹配单个数字 | [ 0 - 9 ] |
| \D | 匹配非数字 | [ ^0 - 9 ] |
| \w | 匹配单词字符(字母、数字、下划线) | [a-zA-Z0-9_] |
| \W | 匹配非单词字符 | [^a-zA-Z0-9_] |
| \s | 匹配空白字符(空格、换行、制表符等) | [ \t \n \r \v \f ] |
| \S | 匹配非空白字符 | [^ \t \n \r \v \f ] |
| . | 匹配除换行符外的任意单个字符 | - |
**注意:**在字符类[ ]中,.会失去特殊含义,仅表示普通点字符,无需转义。
2.5 分组与捕获
使用 () 可以将子模式分组,通常用于:
- 将量词作用于一组字符:(ab)+ 匹配 ab、abab 等。
- **捕获分组:**括号内的内容会被捕获,可以通过 1、2 等引用。
实战示例:日期格式转换
javascript
// 分组捕获年、月、日,三个括号对应三个分组
const reg = /(\d{4})-(\d{2})-(\d{2})/;
const date = '2025-03-31';
// $1对应第一个分组(年),$2对应第二个(月),$3对应第三个(日)
console.log(date.replace(reg, '$2/$3/$1')); // 03/31/2025
2.6 分支结构:实现 "或" 匹配
用|表示或关系,匹配多个规则中的任意一个,适用于多场景并行匹配。
javascript
// 匹配包含java或前端的字符串,无需编写两个正则
const reg = /java|前端/;
reg.test('学前端,练正则'); // true
reg.test('学java,懂编程'); // true
三、前端高频实战案例
1. 基础密码格式验证(6-16 位字母、数字、下划线)
javascript
// 规则:长度6-16位,仅允许字母、数字、下划线
const pwdReg = /^[a-zA-Z0-9_]{6,16}$/;
pwdReg.test('hello2025'); // true
pwdReg.test('123'); // false(长度不足)
2. 标准密码强度验证(含大小写、数字,8-20 位)
javascript
// 规则:8-20位,必须包含小写字母、大写字母、数字,满足常规安全要求
const strongPwdReg = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).{8,20}$/;
strongPwdReg.test('Abc123456'); // true
strongPwdReg.test('abc123456'); // false(无大写字母)
3. 匹配 16 进制颜色值
javascript
// 支持6位标准色值(#f0f0f0)和3位简写色值(#fff)
const colorReg = /^#([0-9a-fA-F]{6}|[0-9a-fA-F]{3})$/;
colorReg.test('#f0f0f0'); // true
colorReg.test('#fff'); // true
colorReg.test('#ggg'); // false(超出范围)
4. 24 小时制时间格式验证
javascript
// 规则:小时00-23,分钟00-59,格式HH:MM,适配时间选择器校验
const timeReg = /^([01][0-9]|2[0-3]):[0-5][0-9]$/;
timeReg.test('23:59'); // true
timeReg.test('08:30'); // true
timeReg.test('24:00'); // false(小时超出范围)
5. 手机号脱敏
javascript
// 规则:保留前3位+后4位,中间4位替换为****,保护用户隐私
const mobile = '15812345678';
const maskReg = /^(\d{3})\d{4}(\d{4})$/;
console.log(mobile.replace(maskReg, '$1****$2')); // 158****5678
6. 手机号格式合法性验证
javascript
// 规则:1开头,第二位3-9,共11位数字,符合国内手机号号段规范
const phoneReg = /^1[3-9]\d{9}$/;
phoneReg.test('13812345678'); // true
phoneReg.test('12812345678'); // false(第二位非法)
四、进阶核心知识点
1. 贪婪与非贪婪匹配
正则量词默认是贪婪匹配 ,会尽可能多的匹配字符;在量词后加?,则变为非贪婪匹配,尽可能少的匹配字符,是提取标签、截取内容的关键技巧。
- 贪婪匹配(默认):.*,能多吃绝不少吃,匹配最长结果
- 非贪婪匹配:.*?,能少吃绝不多吃,匹配最短结果
实战示例:
javascript
const str = '<div>hello</div><div>world</div>';
// 贪婪匹配:匹配整个字符串,吃到最后一个>停止
console.log(str.match(/<.*>/));
//结果:["<div>hello</div><div>world</div>"]
// 非贪婪匹配+全局g:匹配单个标签,遇到第一个>就停止
console.log(str.match<.*?>/g));
// 结果:["<div>", "</div>", "<div>", "</div>"]
2. 前瞻断言(零宽断言)
前瞻断言也叫零宽断言 ,核心特点:只做条件判断,不匹配字符、不占位置、不消耗内容。
2.1 正向前瞻:(?= 条件)
语法:(?= XXX)
含义: 某个位置后面必须紧跟 xxx,才允许匹配,可多个并排叠加,同时满足多个条件。
实例解析:
javascript
// 正向前瞻叠加,同时满足三个条件
(?=.*[a-z]) // 字符串中必须包含至少一个小写字母
(?=.*[A-Z]) // 字符串中必须包含至少一个大写字母
(?=.*\d) // 字符串中必须包含至少一个数字
const pwdReg = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).{8,20}$/;
**执行逻辑:**从字符串开头开始,依次校验是否包含小写、大写、数字,全部满足后,再校验整体长度 8-20 位,且字符顺序不限。
2.2 负向前瞻:(?! 条件)
语法:(?! XXX)
含义: 某个位置后面一定不能出现 xxx,用于排除违规内容。
实战示例:
javascript
// 规则:长度至少6位,且不能全是数字
const noPureNumReg = /^(?!^\d+$).{6,}$/;
noPureNumReg.test('123456'); // false(纯数字,违规)
noPureNumReg.test('abc123'); // true(合规)
扩展:含特殊符号的强密码正则
javascript
// 8-20位+小写+大写+数字+特殊符号(!@#$%^&*)
const superPwdReg = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[!@#$%^&*]).{8,20}$/;