正则表达式:为什么它是前端开发的必备技能? 🌟
正则表达式(Regular Expression)是一种**模式匹配语言**,能高效处理字符串的**搜索、替换、验证和提取**操作。 **核心价值**: - ⚡ **代码更简洁**:1行正则可能替代50行普通逻辑代码 - ⚡ **性能更高效**:底层优化过的正则引擎比手动遍历快数倍 - ⚡ **场景更普适**:从表单验证到日志分析无处不在
七大应用场景:
javascript
// 场景1:表单验证(手机号/邮箱)
const phoneReg = /^1[3-9]\d{9}$/;
const emailReg = /^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/;
// 场景2:数据清洗(去除HTML标签)
const cleanHTML = str => str.replace(/<[^>]+>/g, "");
// 场景3:路由解析(Vue Router)
const path = "/user/123/profile";
const match = path.match(/^\/user\/(\d+)\/(\w+)$/);
console.log(match?.[1]); // "123"
// 其他场景:字符串格式化、敏感词过滤、日志提取、多语言处理...
正则表达式基础:从创建到运行全流程 🛠️
1️⃣ 两种创建方式详解
javascript
// 方式一:字面量(静态正则首选)
const reg1 = /\d{3}/g;
// 方式二:构造函数(动态生成正则必备)
const dynamicPattern = "\\d{3}"; // 从配置读取
const reg2 = new RegExp(dynamicPattern, "gi");
// 对比差异:
console.log(reg1.source); // "\\d{3}"
console.log(reg2.test("123")); // true
2️⃣ 三大修饰符原理剖析
修饰符 | 作用 | 示例 | |
---|---|---|---|
g |
全局匹配(匹配所有结果) | "a1a2".match(/a/g) → ["a","a"] |
|
i |
忽略大小写 | "Apple".match(/apple/i) → ["Apple"] |
|
m |
多行模式(^/$匹配每行首尾) | `"a\nb".match(/^a | b$/gm)→ ["a","b"]` |
javascript
// 多行模式实战:提取每行开头的数字
const text = `1.苹果
2.香蕉
3.橘子`;
console.log(text.match(/^\d+/gm)); // ["1","2","3"]
元字符与字符类:构建匹配规则的核心积木 🧩
1️⃣ 20+元字符速查表
元字符 | 含义 | 等价写法 |
---|---|---|
\d |
数字字符 | [0-9] |
\w |
单词字符(字母数字下划线) | [a-zA-Z0-9_] |
\s |
空白符(空格/制表符等) | [ \t\r\n\v\f] |
. |
除换行外的任意字符 | --- |
^ |
字符串开始 | --- |
$ |
字符串结束 | --- |
2️⃣ 字符类的进阶用法
javascript
// 范围组合:匹配16进制颜色字符
const hexReg = /^#?([a-fA-F0-9]{6}|[a-fA-F0-9]{3})$/;
// 取反技巧:匹配非字母字符
const nonAlpha = /[^a-zA-Z]/g;
console.log("Hello123!".replace(nonAlpha, "_")); // "Hello___"
量词与模式:精准控制匹配次数 🎯
1️⃣ 六种量词对照表
量词 | 含义 | 示例 |
---|---|---|
{n} |
精确n次 | \d{4} → 4位数字 |
{n,} |
至少n次 | \w{3,} → 至少3位 |
{n,m} |
n到m次 | \s{1,3} → 1-3个空格 |
? |
0或1次(可选) | -?\d+ → 正负数 |
+ |
1次或多次 | [a-z]+ → 至少1个字母 |
* |
0次或多次 | .* → 任意字符(含空) |
2️⃣ 贪婪模式 vs 非贪婪模式
javascript
// 贪婪模式(默认):尽可能多吃字符
const greedy = /<div>.*<\/div>/;
"<div>Hello</div><div>World</div>".match(greedy)?[0]; // 匹配整个字符串
// 非贪婪模式(加?):点到为止
const lazy = /<div>.*?<\/div>/g;
"<div>A</div><div>B</div>".match(lazy); // ["<div>A</div>", "<div>B</div>"]
分组与断言:实现复杂匹配逻辑 🧠
1️⃣ 分组的三大妙用
javascript
// 用法1:重复分组内容
const repeatReg = /(bye\s){2}/;
console.log(repeatReg.test("bye bye ")); // true
// 用法2:或逻辑(|)
const osReg = /Win(dows)?10|macOS|Linux/;
// 用法3:捕获分组(替换时用$n引用)
const dateReg = /(\d{4})-(\d{2})-(\d{2})/;
"2023-09-15".replace(dateReg, "$2月$3日"); // "09月15日"
2️⃣ 零宽断言:匹配位置而非内容
断言类型 | 语法 | 含义 |
---|---|---|
正向前瞻 | (?=...) |
后面必须满足条件 |
负向前瞻 | (?!...) |
后面必须不满足条件 |
正向后瞻 | (?<=...) |
前面必须满足条件 |
负向后瞻 | (?<!...) |
前面必须不满足条件 |
javascript
// 实战:密码必须包含字母和数字
const pwdReg = /^(?=.*[a-zA-Z])(?=.*\d).{6,12}$/;
// 实战:提取价格中的数字
const price = "¥123.45元";
console.log(price.match(/(?<=¥)\d+\.?\d*/)); // ["123.45"]
RegExp对象与字符串方法深度解析 🔍
1️⃣ RegExp对象的两大方法
javascript
// test():快速验证
const reg = /\d+/;
console.log(reg.test("abc123")); // true
// exec():逐步获取匹配(需循环)
const reg = /\d+/g;
let result;
while ((result = reg.exec("a1 b2 c3")) !== null) {
console.log(`找到 ${result[0]} 位置:${result.index}`);
}
// 输出:
// 找到 1 位置:1
// 找到 2 位置:4
// 找到 3 位置:7
2️⃣ 字符串四大方法
javascript
// search():查找位置
"hello".search(/ell/); // 1
// match():提取匹配项
"a1 b2".match(/\d/g); // ["1","2"]
// split():高级分割
"2023-09-15".split(/-/); // ["2023","09","15"]
// replace():超级替换(支持函数)
"border-top".replace(/-(\w)/g, (_, c) => c.toUpperCase()); // "borderTop"
六大实战案例:学以致用才是王道 💪
案例1:敏感词过滤系统
javascript
const sensitiveWords = ["暴力", "色情", "诈骗"];
const reg = new RegExp(sensitiveWords.join("|"), "g");
const text = "禁止传播暴力或色情内容";
console.log(text.replace(reg, "***")); // "禁止传播***或***内容"
案例2:Markdown标题提取
javascript
const mdText = `# 标题1
## 标题2
正文内容`;
const headings = mdText.match(/^#+\s(.+)$/gm);
// ["# 标题1", "## 标题2"]
案例3:驼峰命名转换
javascript
function toCamelCase(str) {
return str.replace(/[-_](.)/g, (_, c) => c.toUpperCase());
}
console.log(toCamelCase("user-name")); // "userName"
案例4:千分位数字格式化
javascript
const number = 1234567.89;
number.toFixed(2).replace(/\B(?=(\d{3})+(?!\d))/g, ","); // "1,234,567.89"
案例5:URL参数解析
javascript
const url = "https://example.com?name=John&age=30";
const params = {};
url.replace(/([^?=&]+)=([^&]*)/g, (_, k, v) => params[k] = v);
console.log(params); // {name: "John", age: "30"}
案例6:代码高亮处理
javascript
const code = "let x = 123; // 注释";
const highlighted = code
.replace(/\/\/.*/g, '<span class="comment">$&</span>')
.replace(/\b(let)\b/g, '<span class="keyword">$1</span>');
// 输出带高亮标签的HTML
避坑指南:正则常见误区 ❌
-
过度贪婪 :忘记加
?
导致匹配范围过大❌
/<div>.*<\/div>/
可能吃掉多个div标签✅ 用
/<div>.*?<\/div>/g
实现精准匹配 -
转义错误 :忘记转义特殊字符
❌
new RegExp("a.b")
会匹配"aXb"✅
new RegExp("a\\.b")
或/a\.b/
-
性能陷阱 :灾难性回溯
❌
/(a+)+b/
匹配"aaaaaaaaac"时会卡死✅ 优化为
/a+b/
-
编码问题 :中文字符范围
❌
/[一-龥]/
可能不准确✅ 用Unicode属性
/\p{Script=Han}/u
正则可视化工具推荐 🔧
🌈 写在最后
正则表达式如同编程世界的魔法咒语,掌握它即可轻松驾驭字符串处理。本篇从基础语法到实战案例,从工具推荐到避坑指南,构建了完整的正则知识体系。建议收藏本文作为案头手册,在实践中不断磨练正则技艺!