正则表达式从入门到飞升:覆盖90%前端场景的秘籍

721 阅读2分钟

正则表达式:为什么它是前端开发的必备技能? 🌟

image.png

正则表达式(Regular Expression)是一种模式匹配语言,能高效处理字符串的搜索、替换、验证和提取操作。
核心价值

  • 代码更简洁:1行正则可能替代50行普通逻辑代码
  • 性能更高效:底层优化过的正则引擎比手动遍历快数倍
  • 场景更普适:从表单验证到日志分析无处不在

七大应用场景

// 场景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️⃣ 两种创建方式详解

// 方式一:字面量(静态正则首选)
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"]
// 多行模式实战:提取每行开头的数字
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️⃣ 字符类的进阶用法

// 范围组合:匹配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 非贪婪模式

// 贪婪模式(默认):尽可能多吃字符
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️⃣ 分组的三大妙用

// 用法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️⃣ 零宽断言:匹配位置而非内容

断言类型语法含义
正向前瞻(?=...)后面必须满足条件
负向前瞻(?!...)后面必须不满足条件
正向后瞻(?<=...)前面必须满足条件
负向后瞻(?<!...)前面必须不满足条件
// 实战:密码必须包含字母和数字
const pwdReg = /^(?=.*[a-zA-Z])(?=.*\d).{6,12}$/;

// 实战:提取价格中的数字
const price = "¥123.45元";
console.log(price.match(/(?<=¥)\d+\.?\d*/)); // ["123.45"]

RegExp对象与字符串方法深度解析 🔍

1️⃣ RegExp对象的两大方法

// 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️⃣ 字符串四大方法

// 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:敏感词过滤系统

const sensitiveWords = ["暴力", "色情", "诈骗"];
const reg = new RegExp(sensitiveWords.join("|"), "g");
const text = "禁止传播暴力或色情内容";
console.log(text.replace(reg, "***")); // "禁止传播***或***内容"

案例2:Markdown标题提取

const mdText = `# 标题1
## 标题2
正文内容`;
const headings = mdText.match(/^#+\s(.+)$/gm); 
// ["# 标题1", "## 标题2"]

案例3:驼峰命名转换

function toCamelCase(str) {
  return str.replace(/[-_](.)/g, (_, c) => c.toUpperCase());
}
console.log(toCamelCase("user-name")); // "userName"

案例4:千分位数字格式化

const number = 1234567.89;
number.toFixed(2).replace(/\B(?=(\d{3})+(?!\d))/g, ","); // "1,234,567.89"

案例5:URL参数解析

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:代码高亮处理

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

避坑指南:正则常见误区 ❌

  1. 过度贪婪:忘记加?导致匹配范围过大
    /<div>.*<\/div>/ 可能吃掉多个div标签
    ✅ 用/<div>.*?<\/div>/g实现精准匹配

  2. 转义错误:忘记转义特殊字符
    new RegExp("a.b") 会匹配"aXb"
    new RegExp("a\\.b")/a\.b/

  3. 性能陷阱:灾难性回溯
    /(a+)+b/ 匹配"aaaaaaaaac"时会卡死
    ✅ 优化为/a+b/

  4. 编码问题:中文字符范围
    /[一-龥]/ 可能不准确
    ✅ 用Unicode属性/\p{Script=Han}/u


正则可视化工具推荐 🔧

  1. Regex101:在线测试+逐步解释
  2. Regulex:正则表达式可视化
  3. Debuggex:交互式流程图

🌈 写在最后

正则表达式如同编程世界的魔法咒语,掌握它即可轻松驾驭字符串处理。本篇从基础语法到实战案例,从工具推荐到避坑指南,构建了完整的正则知识体系。建议收藏本文作为案头手册,在实践中不断磨练正则技艺!