跳到主要内容前端正则表达式实战指南:语法、API 与高频场景避坑 | 极客日志JavaScript大前端算法
前端正则表达式实战指南:语法、API 与高频场景避坑
综述由AI生成正则表达式作为前端处理字符串匹配的核心工具,涵盖基础语法、修饰符、API 调用及实战场景。梳理了字面量与构造函数创建方式,详解贪婪懒惰匹配、分组捕获、断言等关键概念,并针对 lastIndex 陷阱、HTML 解析误区及性能回溯爆炸提供避坑方案。结合表单校验、文本提取及倍数判断案例,帮助开发者系统掌握正则编写与调试技巧。
山野来信17 浏览 一、正则表达式到底是什么
一句话定义: 正则表达式(Regular Expression,简称 regex 或 regexp)是一套用来描述字符串匹配模式的微型语言。
你可以把它理解成一个"字符串筛子"——你定义一个模式,然后让字符串从筛子里过,符合模式的留下,不符合的滤掉。
前端工程师每天都在用正则,只是你可能没意识到:
| 场景 | 你在干什么 |
|---|
| 表单校验手机号、邮箱、身份证 | 用正则判断输入是否合法 |
str.replace(/\s+/g, '-') | 用正则做字符串替换 |
Webpack/Vite 配置 test: /.tsx?$/ | 用正则匹配文件后缀 |
| ESLint 规则配置 | 用正则匹配代码模式 |
路由匹配 /user/:id(\d+) | 用正则约束参数格式 |
| 从接口返回的 HTML 里提取内容 | 用正则做文本提取 |
正则不是什么高深的东西,它就是前端的日常工具。但很多人用了好几年还是"面向搜索引擎写正则",根本原因是——基础语法没有系统地过一遍。
今天我们就从零开始,一块一块拼完整。
二、正则的两种创建方式
在 JavaScript 里,创建正则有两种方式:
2.1 字面量写法(推荐日常使用)
const reg = /abc/g;
特点:写起来简洁,编译时就确定了模式,不能动态拼接变量。
2.2 构造函数写法(需要动态拼接时用)
const keyword = '前端';
const reg = new RegExp(keyword, 'g');
特点:可以用变量拼接模式,运行时才编译。
2.3 什么时候该用哪种?
| 场景 | 选择 | 原因 |
|---|
| 校验手机号、邮箱等固定模式 | 字面量 /^\d{11}$/ | 模式固定,字面量更简洁 |
| 根据用户输入的关键词做高亮 | 构造函数 new RegExp(keyword, 'gi') | 关键词是动态的 |
| Webpack/Vite 配置文件里匹配文件 | 字面量 /.css$/ | 模式固定 |
2.4 踩坑提醒:构造函数里反斜杠要双写
const reg1 = /\d+/;
const reg2 = new RegExp('\\d+');
const reg3 = new RegExp('\d+');
这是很多人踩过的坑——用 new RegExp 时,字符串本身会先做一层转义,所以 \d 必须写成 \\d。
三、基础语法:一块一块拼出来
正则语法看起来像乱码,但它其实就几个模块拼起来的。我们一个一个来。
3.1 普通字符——就是它自己
/abc/.test('xabcy');
/abc/.test('a-b-c');
字母、数字、汉字这些"普通字符"在正则里就代表它自己,没有特殊含义。
3.2 特殊字符(元字符)——正则的核心能力
| 元字符 | 含义 | 示例 | 匹配 |
|---|
. | 匹配任意一个字符(换行符除外) | /a.c/ | abc、a1c、a c |
\d | 匹配一个数字(等价于 [0-9]) | /\d{3}/ | 123、456 |
\D | 匹配一个非数字 | /\D/ | a、!、空格 |
\w | 匹配一个单词字符(字母、数字、下划线) | /\w+/ | hello、test_1 |
\W | 匹配一个非单词字符 | /\W/ | @、#、空格 |
\s | 匹配一个空白字符(空格、Tab、换行等) | /\s/ | 空格、\t、\n |
\S | 匹配一个非空白字符 | /\S+/ | hello、123 |
\b | 单词边界 | /\bcat\b/ | 匹配 "the cat sat" 中的 cat,不匹配 category |
\B | 非单词边界 | /\Bcat/ | 匹配 category 中的 cat |
记忆技巧: 小写是"某类字符",大写是"取反"。\d = digit,\D = 非 digit;\w = word,\W = 非 word;\s = space,\S = 非 space。
3.3 量词——控制"出现几次"
| 量词 | 含义 | 示例 | 匹配 |
|---|
* | 0 次或多次 | /ab*/ | a、ab、abbb |
+ | 1 次或多次 | /ab+/ | ab、abbb(不匹配单独的 a) |
? | 0 次或 1 次 | /colou?r/ | color、colour |
{n} | 恰好 n 次 | /\d{4}/ | 2025 |
{n,} | 至少 n 次 | /\d{2,}/ | 12、123、1234 |
{n,m} | n 到 m 次 | /\d{2,4}/ | 12、123、1234 |
const phoneReg = /^1[3-9]\d{9}$/;
phoneReg.test('13812345678');
phoneReg.test('12345678901');
phoneReg.test('1381234567');
拆解:^ 开头 + 1 第一位是 1 + [3-9] 第二位是 3 到 9 + \d{9} 后面恰好 9 个数字 + $ 结尾。
3.4 贪婪与懒惰——量词的"性格"
const str = '<div>hello</div><div>world</div>';
str.match(/<div>.*<\/div>/);
str.match(/<div>.*?<\/div>/);
规则很简单:量词后面加一个 ?,就从贪婪变成懒惰。
| 贪婪 | 懒惰 | 区别 |
|---|
* | *? | 尽可能多 → 尽可能少 |
+ | +? | 尽可能多 → 尽可能少 |
{n,m} | {n,m}? | 尽可能多 → 尽可能少 |
实战踩坑: 很多人在用正则提取 HTML 标签内容时被贪婪模式坑过。记住:提取"一对标签之间的内容"时,中间的匹配部分通常用 .*?(懒惰模式)而不是 .*(贪婪模式)。
3.5 字符集(字符类)——'这些字符里任选一个'
用方括号 [] 定义一个字符集,表示方括号里的字符任选一个。
/[abc]/.test('apple');
/[abc]/.test('dog');
/[0-9]/.test('hello3');
/[a-zA-Z]/.test('你好');
| 写法 | 含义 |
|---|
[abc] | a 或 b 或 c |
[a-z] | a 到 z 的任意小写字母 |
[A-Z] | 任意大写字母 |
[0-9] | 任意数字(等价于 \d) |
[a-zA-Z0-9_] | 字母 + 数字 + 下划线(等价于 \w) |
[^abc] | 取反:除了 a/b/c 以外的任意字符 |
[^0-9] | 非数字(等价于 \D) |
注意: 方括号里的 ^ 是取反的意思,别和正则开头的 ^(锚点)搞混了。
3.6 锚点——'在哪个位置匹配'
| 锚点 | 含义 | 示例 |
|---|
^ | 字符串的开头 | /^hello/ —— 以 hello 开头 |
$ | 字符串的结尾 | /world$/ —— 以 world 结尾 |
\b | 单词边界 | /\bJS\b/ —— 匹配独立的 JS,不匹配 JSON 里的 JS |
/\d{11}/.test('abc13812345678xyz');
/^\d{11}$/.test('abc13812345678xyz');
/^\d{11}$/.test('13812345678');
不加锚点,正则只是检查字符串里"是否包含"这个模式,而不是"整体是否匹配"。表单校验不加 ^$ 是经典新手坑。
3.7 分组与捕获——用小括号 () 打包
/ab+/.test('abbb'); // true —— + 只作用于 b
/(ab)+/.test('ababab'); // true —— + 作用于整个 ab
const dateStr = '2025-02-22';
const match = dateStr.match(/(\d{4})-(\d{2})-(\d{2})/);
console.log(match[0]);
console.log(match[1]);
console.log(match[2]);
console.log(match[3]);
const dateStr = '2025-02-22';
const match = dateStr.match(/(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/);
console.log(match.groups.year);
console.log(match.groups.month);
console.log(match.groups.day);
语法:(?<名字>模式),用 match.groups.名字 获取。比数字索引可读性好太多。
有时候你只是想分组,但不需要捕获结果(节省内存、让捕获组编号更清晰):
const match = 'abc123'.match(/(?:abc)(\d+)/);
console.log(match[1]);
3.8 或运算——用 | 表示"或者"
/cat|dog/.test('I have a cat');
/cat|dog/.test('I have a dog');
/cat|dog/.test('I have a fish');
/cat|dog/
gr(a|e)y
/\.(png|jpe?g|gif|webp|svg)$/i
3.9 反向引用——引用前面捕获的内容
const reg = /(\w+)\s+\1/;
reg.test('hello hello');
reg.test('hello world');
四、修饰符(Flags)——正则的"全局配置"
| 修饰符 | 名称 | 含义 |
|---|
g | global | 全局匹配,找到所有匹配项(不只是第一个) |
i | ignoreCase | 忽略大小写 |
m | multiline | 多行模式,^ 和 $ 匹配每一行的开头结尾 |
s | dotAll | 让 . 也能匹配换行符(ES2018) |
u | unicode | 启用 Unicode 匹配(ES6) |
y | sticky | 粘性匹配,从 lastIndex 位置开始 |
4.1 最常用的三个:g、i、m
'aaa'.match(/a/);
'aaa'.match(/a/g);
/hello/i.test('Hello');
const text = 'line1\nline2\nline3';
text.match(/^\w+/g);
text.match(/^\w+/gm);
4.2 s 修饰符——让 . 匹配换行符
const html = '<div>\nhello\n</div>';
html.match(/<div>(.+)<\/div>/);
html.match(/<div>(.+)<\/div>/s);
4.3 u 修饰符——正确处理 Unicode
'😀'.match(/^.$/);
'😀'.match(/^.$/u);
/\u{61}/u.test('a');
建议: 只要你的正则可能接触非 ASCII 字符(中文、emoji 等),就加上 u。
五、JavaScript 中正则相关的 API——到底该用哪个
这是很多人搞混的地方。JS 里正则相关的方法分布在 RegExp 原型和 String 原型上,功能有重叠,选错了就踩坑。
5.1 全家福一览
| 方法 | 属于 | 返回值 | 常见用途 |
|---|
reg.test(str) | RegExp | true/false | 判断是否匹配 |
reg.exec(str) | RegExp | 匹配数组 或 null | 逐个提取匹配(配合循环) |
str.match(reg) | String | 匹配数组 或 null | 一次性获取匹配 |
str.matchAll(reg) | String | 迭代器 | 获取所有匹配及其捕获组(ES2020) |
str.search(reg) | String | 索引 或 -1 | 查找第一个匹配的位置 |
str.replace(reg, replacement) | String | 新字符串 | 替换匹配的内容 |
str.replaceAll(reg, replacement) | String | 新字符串 | 替换所有匹配(ES2021) |
str.split(reg) | String | 数组 | 按匹配模式分割字符串 |
5.2 逐个说清楚
test —— 最简单,只问"有没有"
/\d/.test('hello123');
/\d/.test('hello');
const reg = /a/g;
reg.test('aaa');
reg.test('aaa');
reg.test('aaa');
reg.test('aaa');
reg.test('aaa');
原因:带 g 的正则对象有一个 lastIndex 属性,每次 test/exec 调用后会更新,下次从 lastIndex 位置继续找。
- 如果只是判断"有没有",不要加
g
- 或者每次用前手动
reg.lastIndex = 0
- 或者用字面量直接写
/a/.test(str)(每次创建新正则)
match —— 获取匹配结果
const str = 'a1b2c3';
str.match(/([a-z])(\d)/);
str.match(/([a-z])(\d)/g);
这是 match 最大的设计问题:加了 g 就拿不到捕获组。 怎么办?用 matchAll。
matchAll —— 完美获取所有匹配 + 捕获组(推荐)
const str = 'a1b2c3';
const matches = str.matchAll(/([a-z])(\d)/g);
for (const match of matches) {
console.log(match[0], match[1], match[2]);
}
matchAll 返回一个迭代器,每个元素都包含完整的匹配信息和捕获组。这是 ES2020 之后提取多个匹配的最佳方式。
replace —— 替换匹配内容
'hello world'.replace(/world/, '前端');
'aaa'.replace(/a/, 'b');
'aaa'.replace(/a/g, 'b');
'2025-02-22'.replace(/(\d{4})-(\d{2})-(\d{2})/, '$2/$3/$1');
'hello world'.replace(/\b\w/g, (char) => char.toUpperCase());
replace 的第二个参数可以是函数,这是正则最强大的用法之一。
函数的参数:(match, p1, p2, ..., offset, string)
const html = '访问 <a href="https://example.com">示例</a> 网站';
const result = html.replace(/<a href="([^"]+)">([^<]+)<\/a>/g, (match, url, text) => `[${text}](${url})`);
split —— 用正则分割字符串
'a, b,c , d'.split(/,\s*/);
'2025-02/22'.split(/[-/]/);
'hello world foo'.split(/\s+/);
六、前端实战:高频正则模式
6.1 表单校验系列
const phoneReg = /^1[3-9]\d{9}$/;
const emailReg = /^[\w.-]+@[\w-]+(\.[\w-]+)+$/;
const idCardReg = /^\d{17}[\dXx]$/;
const pwdReg = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[a-zA-Z\d@$!%*?&]{8,}$/;
const urlReg = /^https?:\/\/[^\s]+$/;
关于密码正则的 (?=...) 语法: 这叫正向先行断言(Lookahead),下一节会详细讲。
6.2 字符串处理系列
str.replace(/^\s+|\s+$/g, '');
str.replace(/\s+/g, ' ');
'backgroundColor'.replace(/[A-Z]/g, (char) => '-' + char.toLowerCase());
'background-color'.replace(/-([a-z])/g, (_, char) => char.toUpperCase());
'1234567'.replace(/\B(?=(\d{3})+$)/g, ',');
function getParams(url) {
const params = {};
url.replace(/[?&]([^=&#]+)=([^&#]*)/g, (_, key, value) => {
params[decodeURIComponent(key)] = decodeURIComponent(value);
});
return params;
}
getParams('https://example.com?name=张三&age=25');
6.3 内容提取系列
const md = ' ';
const images = [...md.matchAll(/!\[([^\]]*)\]\(([^)]+)\)/g)].map(m => ({ alt: m[1], src: m[2] }));
const html = '<div><span>text</span><img/></div>';
const tags = [...html.matchAll(/<\/?([\w]+)/g)].map(m => m[1]);
6.4 趣味实战:正则匹配数字倍数
很多同学会好奇:正则能不能直接匹配 3 或 7 的倍数?答案是"可以,但分场景"。
首先要明确一个最基础的点:正则是匹配字符串的工具(比如匹配手机号、邮箱),它本来就不是用来"算数学题"的(比如判断 3 的倍数)。就像你拿菜刀能勉强拧螺丝,但效率低、还容易出错——正则匹配倍数就是这个道理,能做,但不是最优解。
生产环境里,我们判断一个数字是不是 3 的倍数,直接这么写:
const num = 123;
console.log(num % 3 === 0);
这行代码的意思是:123 除以 3,余数是不是 0?是就是 3 的倍数。简单、好懂、不出错。
而"用正则匹配 3 的倍数",本质是"绕个弯"——把"数学计算"转化成"字符串规律匹配",纯粹是练手/面试趣味题,不是正经干活的写法。
第一部分:先搞懂"3 的倍数"到底有啥规律?
不用管正则,先记一个小学数学知识点:一个数,把它的每一位数字加起来,如果和能被 3 整除,那这个数就是 3 的倍数。
- 123:1+2+3=6 → 6 能被 3 整除 → 123 是 3 的倍数;
- 4567:4+5+6+7=22 → 22÷3 余 1 → 不是 3 的倍数;
- 0:0÷3=0 → 也是 3 的倍数。
这个规律是关键!正则能"匹配"3 的倍数,全靠这个规律——因为正则看不懂"123"是数字,但能拆成"1""2""3"三个字符,然后我们用代码把这三个字符加起来,判断和是不是 3 的倍数。
"3 的倍数"代码(逐行解释)
function isMultipleOf3(str) {
const isPureNumber = /^\d+$/.test(str);
if (!isPureNumber) return false;
const digitList = str.split('');
let sum = 0;
for (let i = 0; i < digitList.length; i++) {
sum = sum + Number(digitList[i]);
}
return sum % 3 === 0;
}
console.log(isMultipleOf3("0"));
console.log(isMultipleOf3("12"));
console.log(isMultipleOf3("124"));
你看,这里虽然用了正则(/^\d+$/),但它只负责"校验是不是纯数字",真正判断 3 的倍数的,还是"求和→取模"这个数学逻辑。
第二部分:7 的倍数为啥更麻烦?
7 的倍数没有 3 那么简单的"求和规律",它的规律是"递归减法",可以记这个口诀:把数字最后一位抠出来×2,用前面的数减去这个结果,要是差是 7 的倍数,那原数就是 7 的倍数。
- 最后一位是 1 → 1×2=2;
- 前面的数是 16 → 16-2=14;
- 14 是 7 的倍数 → 所以 161 是 7 的倍数。
"7 的倍数"代码(逐行解释)
function isMultipleOf7(str) {
if (!/^\d+$/.test(str)) return false;
let tempStr = str;
while (tempStr.length > 1) {
const lastDigit = tempStr.slice(-1);
const restDigit = tempStr.slice(0, -1) || "0";
const diff = Math.abs(BigInt(restDigit) - 2n * BigInt(lastDigit));
tempStr = diff.toString();
}
return /^(0|7)$/.test(tempStr);
}
console.log(isMultipleOf7("0"));
console.log(isMultipleOf7("161"));
console.log(isMultipleOf7("1234"));
最后:必须记住的 3 个关键点
- 别钻牛角尖:正则的核心作用是"匹配字符串模式",不是"算数学题";判断 3/7 的倍数,优先用"转数字→取模",简单又不容易错;
- 3 的倍数规律:各位数字相加的和能被 3 整除,这是最容易理解的规律;
- 7 的倍数规律:最后一位×2,前面的数减这个结果,递归到只剩 1 位,看是不是 0/7 就行。
七、进阶语法:断言(Lookaround)
断言是正则里"看起来最唬人,但用对了最强大"的语法。它不消耗字符,只做判断。
7.1 四种断言
| 语法 | 名称 | 含义 |
|---|
(?=...) | 正向先行断言 | 后面是 … |
(?!...) | 负向先行断言 | 后面不是 … |
(?<=...) | 正向后行断言 | 前面是 … |
(?<!...) | 负向后行断言 | 前面不是 … |
7.2 正向先行断言 (?=...)
'100 元 200 美元 300 元'.match(/\d+(?=元)/g);
'1234567'.replace(/\B(?=(\d{3})+$)/g, ',');
7.3 负向先行断言 (?!..)
'width:100px;height:200;margin:30em'.match(/\d+(?!px|em)/g);
7.4 后行断言 (?<=...) 和 (?<!...)(ES2018)
'$100 ¥200 $300'.match(/(?<=\$)\d+/g);
'$100 ¥200 $300'.match(/(?<!\$)\d+/g);
7.5 密码强度校验——断言的经典应用
const strongPwd = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).{8,}$/;
^ 和 $:整体匹配
(?=.*[a-z]):先行断言——某处有小写字母
(?=.*[A-Z]):先行断言——某处有大写字母
(?=.*\d):先行断言——某处有数字
.{8,}:任意字符至少 8 个
多个先行断言可以叠加,它们都在同一个位置做检查,互不干扰。
八、真实踩坑案例
8.1 坑 1:/g 的 lastIndex 陷阱
const emailReg = /^[\w.-]+@[\w-]+(\.[\w-]+)+$/g;
function isValidEmail(email) {
return emailReg.test(email);
}
isValidEmail('[email protected]');
isValidEmail('[email protected]');
原因: 带 g 的正则有 lastIndex 状态。第一次匹配成功后 lastIndex 指向字符串末尾,第二次从末尾开始找,当然找不到。
修复: 校验场景不要用 g,test 只需要知道"有没有",不需要"找所有"。
8.2 坑 2:match 加了 g 丢失捕获组
const str = '2025-02-22, 2024-01-15';
const result = str.match(/(\d{4})-(\d{2})-(\d{2})/g);
const matches = [...str.matchAll(/(\d{4})-(\d{2})-(\d{2})/g)];
matches.forEach(m => {
console.log(`年:${m[1]} 月:${m[2]} 日:${m[3]}`);
});
8.3 坑 3:忘了转义特殊字符
/3.14/.test('3X14');
/3\.14/.test('3X14');
/3\.14/.test('3.14');
需要转义的特殊字符: \ . * + ? ^ $ { } [ ] ( ) | /
当你用 new RegExp 从用户输入构造正则时,一定要先转义:
function escapeRegExp(str) {
return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
}
const userInput = 'price: $9.99 (USD)';
const safeReg = new RegExp(escapeRegExp(userInput));
safeReg.test('price: $9.99 (USD)');
8.4 坑 4:用正则解析 HTML——不要这么做
const html = '<div><p>hello</p></div>';
const content = html.match(/<div[^>]*>(.*?)<\/div>/s)?.[1];
简单场景能用,但正经解析 HTML 请用 DOM API:
const parser = new DOMParser();
const doc = parser.parseFromString(html, 'text/html');
const content = doc.querySelector('div.box').innerHTML;
为什么?HTML 可以嵌套、可以有注释、可以有各种边界情况,正则处理不了递归结构。
规则:正则做简单的文本匹配和提取可以;解析结构化数据(HTML、JSON),用专门的解析器。
8.5 坑 5:正则性能——回溯爆炸
const evilReg = /^(a+)+$/;
evilReg.test('aaaaaaaaaa');
evilReg.test('aaaaaaaaaaaaaaaaaaaaaaaab');
原因:(a+)+ 有多种方式分配 a 的归属,当最后无法匹配时,引擎会逐一尝试所有可能(回溯),时间复杂度指数级增长。
- 避免嵌套量词:
(a+)+、(a*)*、(a+)* 这类写法都危险
- 可以改写为
a+,效果一样但不会回溯爆炸
- 生产环境接受用户输入的正则时,要做超时保护
九、正则调试工具推荐
强烈推荐 regex101.com——你把正则贴进去,它会逐字符给你解释这个正则在干什么,还能看到匹配的步骤。比盯着正则硬猜高效一百倍。
十、面试怎么答
面试官问"说说你对正则表达式的理解"或者"正则在前端有什么应用",可以这样组织:
正则表达式是一套描述字符串匹配模式的语法。在前端开发中主要用于表单校验、字符串处理、文本提取和替换。
我在日常工作中经常用正则做表单校验(手机号、邮箱等)、用 replace 配合捕获组做格式转换(比如日期格式、驼峰命名转换)、在构建工具配置中用正则匹配文件类型。
比如带 g 标志的正则有 lastIndex 状态,在循环校验场景下会出现时灵时不灵的 bug。再比如贪婪匹配和懒惰匹配的区别——提取标签内容时如果用了贪婪模式,会匹配到最后一个闭合标签,通常需要用 .*? 懒惰模式。
写正则时要避免嵌套量词导致的灾难性回溯,尤其是在处理用户输入时。对于复杂的结构化数据(如 HTML),应该用 DOMParser 而不是正则。
十一、常用正则速查表
【字符类】
. 任意字符(换行除外,加 s 修饰符则包含换行)
\d 数字 [0-9]
\D 非数字 [^0-9]
\w 单词字符 [a-zA-Z0-9_]
\W 非单词字符
\s 空白字符(空格、Tab、换行等)
\S 非空白字符
[abc] a 或 b 或 c
[^abc] 除了 a、b、c
[a-z] a 到 z
【量词】
* 0 次或多次
+ 1 次或多次
? 0 次或 1 次
{n} 恰好 n 次
{n,} 至少 n 次
{n,m} n 到 m 次
*? +? 懒惰模式(尽可能少匹配)
【锚点】
^ 字符串/行开头
$ 字符串/行结尾
\b 单词边界
\B 非单词边界
【分组与引用】
(abc) 捕获分组
(?:abc) 非捕获分组
(?<name>) 命名捕获
\1 反向引用第 1 个捕获组
$1 replace 中引用第 1 个捕获组
【断言】
(?=...) 正向先行断言(后面是)
(?!...) 负向先行断言(后面不是)
(?<=...) 正向后行断言(前面是)
(?<!...) 负向后行断言(前面不是)
【修饰符】
g 全局匹配
i 忽略大小写
m 多行模式
s dotAll(. 匹配换行)
u Unicode 模式
y 粘性匹配
十二、总结
| 维度 | 说明 |
|---|
| 正则是什么 | 描述字符串匹配模式的微型语言 |
| 核心能力 | 匹配、提取、替换、分割 |
| JS 中最常用的 API | test(校验)、match/matchAll(提取)、replace(替换) |
| 最常踩的坑 | g 的 lastIndex 状态、贪婪 vs 懒惰、忘转义特殊字符 |
| 最佳实践 | 校验不加 g;提取多个用 matchAll;解析 HTML 用 DOM API |
| 调试工具 | https://regex101.com(强烈推荐) |
正则表达式就像 Git——你可以只会最基本的操作活很多年,但系统学一遍之后会发现,之前白费了好多力气。这篇文章覆盖了日常开发 95% 的正则场景,建议收藏,忘了就回来翻翻。
相关免费在线工具
- 加密/解密文本
使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online
- Gemini 图片去水印
基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online
- Keycode 信息
查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online
- Escape 与 Native 编解码
JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online
- JavaScript / HTML 格式化
使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online
- JavaScript 压缩与混淆
Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online