js 正则(长文解析)

更新时间:

💡一则或许对你有用的小广告

欢迎加入小哈的星球 ,你将获得:专属的项目实战(已更新的所有项目都能学习) / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论

  • 新开坑项目:《Spring AI 项目实战》 正在持续爆肝中,基于 Spring AI + Spring Boot 3.x + JDK 21..., 点击查看 ;
  • 《从零手撸:仿小红书(微服务架构)》 已完结,基于 Spring Cloud Alibaba + Spring Boot 3.x + JDK 17...点击查看项目介绍 ;演示链接: http://116.62.199.48:7070 ;
  • 《从零手撸:前后端分离博客项目(全栈开发)》 2 期已完结,演示链接: http://116.62.199.48/ ;

截止目前, 星球 内专栏累计输出 90w+ 字,讲解图 3441+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,权限管理,Spring Cloud Alibaba 微服务等等,已有 3100+ 小伙伴加入学习 ,欢迎点击围观

前言

在 JavaScript 开发中,js 正则表达式是处理字符串的“瑞士军刀”。无论是验证用户输入、提取特定模式的数据,还是替换文本内容,正则表达式都能提供高效且灵活的解决方案。对于编程初学者,它可能显得抽象;但对于中级开发者,掌握它能显著提升代码的简洁性和可维护性。本文将从基础语法到实战案例,逐步解析 js 正则的核心知识点,帮助读者建立系统化的理解。


正则表达式基础语法

基本结构与创建方式

正则表达式由两部分构成:模式(pattern)和修饰符(flags)。在 JavaScript 中,可以通过以下两种方式创建:

  1. 正则字面量:用 / 符号包裹模式,例如 /abc/
  2. 构造函数:通过 new RegExp('pattern', 'flags') 动态生成,适合模式需要动态构建的场景。

示例代码

// 正则字面量  
const regex1 = /hello/;  

// 构造函数(注意转义字符需要双写)  
const regex2 = new RegExp("h[e]llo");  

元字符与字符匹配

正则表达式中,某些字符具有特殊含义,称为“元字符”(如 . * +)。例如:

  • . 匹配任意单个字符(除换行符外);
  • ^ 表示字符串的开头,例如 /^hello/ 仅匹配以 "hello" 开头的文本;
  • $ 表示字符串的结尾,例如 /world$/ 仅匹配以 "world" 结尾的文本。

比喻:可以把正则表达式想象成一张“通缉令”,元字符就是通缉令上的关键线索,例如 . 就像“任意身高的人”,^ 则是“必须穿红色外套入场”。


常见元字符与字符类

特殊字符的转义

若要匹配元字符本身,需用反斜杠 \ 转义。例如:

// 匹配字符 '.'  
const regex = /\./;  
console.log(regex.test("a.b")); // true  

预定义字符类

JavaScript 支持多种字符类,简化常见匹配场景:
| 字符类 | 描述 | 示例模式 |
|-------|--------------------------|------------------------|
| \d | 匹配任意数字(0-9) | /^\d{4}$/ 匹配四位数 |
| \w | 匹配字母、数字或下划线 | /^\w{6,}$/ 基础密码验证 |
| \s | 匹配空白字符(空格、换行等) | /^\s*$/ 判断全空白字符串 |

自定义字符集合

使用方括号 [] 定义字符集合,例如:

  • [abc] 匹配单个字符 a、b 或 c;
  • [^abc] 匹配除 a、b、c 以外的任意单个字符。

案例:验证邮箱域名部分是否为 "com" 或 "cn":

const regex = /\.([c][o][m]|[c][n])$/i;  
console.log(regex.test("example.com")); // true  

量词与模式重复

基本量词

量词控制前面元素的重复次数:
| 量词 | 含义 | 示例模式 |
|------|--------------------|--------------------|
| * | 出现 0 次或多次 | /a*/ 匹配空字符串或多个 a |
| + | 出现 1 次或多次 | /a+/ 匹配至少一个 a |
| ? | 出现 0 次或 1 次 | /colou?r/ 匹配 "color" 或 "colour" |

贪心与非贪心匹配

默认的量词是“贪心”的,即尽可能多匹配。添加 ? 可变为“非贪心”:

const html = "<div>content</div>";  
// 贪心匹配  
console.log(/<.*>/.exec(html)); // ["<div>content</div>"]  
// 非贪心匹配  
console.log(/<.*?>/i.exec(html)); // ["<div>"]  

分组与捕获

捕获组

用小括号 () 定义捕获组,可提取匹配内容:

const url = "https://www.example.com/path";  
const regex = /:\/\/(www\.)?(\w+)\.(\w+)/;  
const matches = url.match(regex);  
console.log(matches[1]); // "www."(如果存在)  
console.log(matches[2]); // "example"  

反向引用

捕获组的内容可在替换时通过 $n 引用:

const text = "Hello World";  
console.log(text.replace(/(\w+) (\w+)/, "$2, $1")); // "World, Hello"  

零宽断言与边界匹配

预查(Lookahead)

预查通过 (?=...)(?!...) 检查当前位置是否满足条件,但不消耗字符:

  • 正向预查/password(?=\d)/ 要求 "password" 后跟数字;
  • 负向预查/password(?!admin)/ 要求 "password" 后不跟 "admin"。

后顾(Lookbehind)

通过 (?<=...)(?<!...) 检查当前位置前的模式:

// 匹配以 http:// 或 https:// 开头的 URL  
const regex = /(?<=^https?://).*$/;  
console.log(regex.exec("http://example.com")); // "example.com"  

实战案例:常见场景应用

案例 1:邮箱验证

const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;  
console.log(emailRegex.test("user@example.com")); // true  

解析

  • ^[a-zA-Z0-9._%+-]+ 匹配用户名部分;
  • @[a-zA-Z0-9.-]+\. 匹配 @ 符号和域名;
  • [a-zA-Z]{2,}$ 确保域名后缀至少两位。

案例 2:密码强度检测

const passwordRegex = /^(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,}$/;  
// 需包含数字、小写字母、大写字母,且长度≥8  

案例 3:提取电话号码国家代码

const phone = "+86 13800138000";  
const regex = /^\+(\d{1,3})/;  
console.log(regex.exec(phone)[1]); // "86"  

性能优化与注意事项

避免“灾难性回溯”

复杂量词组合可能导致正则引擎无限循环,例如 /(a+)+/ 匹配 "aaaa" 时可能崩溃。应尽量简化模式或使用非捕获组 (?:...)

全局匹配与标志位

  • g 标志开启全局匹配,例如 /hello/g 可匹配所有 "hello";
  • i 标志启用大小写不敏感;
  • m 标志支持多行匹配。

结论

js 正则表达式是 JavaScript 开发者的必备工具,其核心在于理解元字符、量词、分组和断言的逻辑关系。通过本文的示例和案例,读者应能掌握从基础语法到复杂场景的应用能力。建议在项目中逐步实践,例如通过验证表单输入、解析日志文件或重构字符串处理代码,进一步巩固技能。记住,正则表达式的设计需平衡简洁性与可读性,避免过度复杂化模式。

提示:在 Chrome 开发者工具的 Console 中输入 /pattern/,可快速测试正则表达式的行为,这对调试非常有帮助。

最新发布