正则表达式
- 正则表达式用于定义一些字符串的规则
- 可以根据正则表达式来检测一个字符串是否符合规则
创建正则表达式
字面量方式
let reg = /abc/;
构造函数方式
let reg = new RegExp("abc");
修饰符(flags)
修饰符 | 含义 |
---|
g | 全局匹配 |
i | 忽略大小写 |
m | 多行模式 |
s | dotAll 模式,. 匹配换行符 |
u | 支持 Unicode |
y | 粘性匹配,从 lastIndex 开始 |
元字符(Metacharacters)
字符 | 含义 |
---|
. | 匹配除换行符外的任意字符 |
^ | 匹配字符串开头 |
$ | 匹配字符串结尾 |
\d | 匹配数字 |
\D | 匹配非数字 |
\w | 匹配字母、数字、下划线 |
\W | 匹配非单词字符 |
\s | 匹配空白字符 |
\S | 匹配非空白字符 |
| 匹配单词边界 |
\B | 匹配非单词边界 |
量词(Quantifiers)
符号 | 含义 |
---|
* | 匹配 0 次或多次 |
+ | 匹配 1 次或多次 |
? | 匹配 0 次或 1 次 |
{n} | 匹配 n 次 |
{n,} | 匹配至少 n 次 |
{n,m} | 匹配 n 到 m 次 |
贪婪与惰性匹配
/a.*b/
/a.*?b/
分组与引用
分组
/(ab)+/
反向引用
/(.)/
非捕获组
/(?:abc)/
命名捕获组(ES2018+)
const str = "2025-04";
const reg = /(?<year>\d{4})-(?<month>\d{2})/;
const result = str.match(reg);
console.log(result.groups.year);
断言(Assertions)
正向肯定断言
/\d(?=px)/
正向否定断言
/\d(?!px)/
反向肯定断言(Lookbehind)
/(?<=\$)\d+/
反向否定断言
/(?<!\$)\d+/
常用方法
RegExp 实例方法
const reg = /abc/;
reg.test("abc");
reg.exec("abcdef");
字符串对象方法
"abc123".match(/\d+/g);
"abc123".search(/\d+/);
"abc123".replace(/\d+/, "#");
"1-2-3".split(/-/);
Unicode 与属性转义(ES2018+)
/\p{Script=Greek}/u
必须搭配 u
修饰符使用。
其他高级用法
多行匹配(m)
/^abc/m
粘性匹配(y)
const reg = /a/y;
reg.lastIndex = 1;
reg.exec("baaa");
🧠 正则表达式的执行原理
正则表达式通常由**NFA 引擎(非确定有限自动机)**或 DFA(确定型自动机)执行:
- NFA(大多数编程语言使用,如 JavaScript、Python):
- 从头到尾尝试多种路径(回溯)。
- 灵活,但可能效率低。
- DFA(如某些命令行工具):
回溯的影响示例:
const regex = /(a+)+$/;
regex.test("aaaaaaaaaaaaaaaaaaaaa!");
这类问题称为 Catastrophic Backtracking(灾难性回溯),匹配失败时会极大拖慢执行速度。
🧩 嵌套分组与命名分组深入用法
命名捕获组(ES2018+):
const str = "Name: Alice Age: 20";
const reg = /Name: (?<name>\w+) Age: (?<age>\d+)/;
const result = str.match(reg);
console.log(result.groups.name);
嵌套组合:
/((foo)(bar))\3/
组号从左至右分配,嵌套也会编号。
🔎 正向/反向断言的高级使用
正向肯定断言:
/\d(?=px)/g
反向肯定断言(Lookbehind):
/(?<=\$)\d+/g
这些对提取特定前后缀的数据特别有用,如提取 CSS 数值、货币值等。
⚙️ 正则性能优化技巧
技巧 | 示例 |
---|
避免重复匹配 | 用 + 替代多个 * |
固定开头 | 使用 ^ 锚定 |
精确限定 | 使用 {m,n} 代替 .* |
惰性匹配 | 用 *? 替代贪婪 * |
非捕获组 | 用 (?:...) 提高效率 |
/.*foo.*bar.*/
/^.*?foo.*?bar/
🛡️ 输入预处理与安全防护
XSS 防护示例:
const sanitized = input.replace(/<script[^>]*>([\s\S]*?)<\/script>/gi, "");
防 SQL 注入:
const hasSQL = /('|--|;|\b(select|insert|delete|update|drop|union)\b)/i.test(userInput);
调试技巧与工具推荐
调试技巧
- 多用
.test()
、.exec()
检查正则效果 - 控制台调试,结合
console.log
- 使用 IDE 高亮或在线工具预览匹配效果
在线工具推荐
名称 | 链接 |
---|
regex101 | https://regex101.com |
regexr | https://regexr.com |
regexper | https://regexper.com |
📚 值得掌握的正则表达式案例
目标 | 正则表达式 |
---|
匹配非重复字符 | ^(?!.*(.).*\1).+$ |
匹配 emoji | /[\uD800-\uDBFF][\uDC00-\uDFFF]/g |
解析 JSON 键值对 | `/“([“]+)”:\s*("[”]+" |
提取 HTML 属性 | /([a-zA-Z-]+)="([^"]*)"/g |
✅ 总结建议
- 正则表达式适合解决字符串匹配和提取问题,但可读性差时应加注释或分步骤处理。
- 建议多练常见应用场景如手机号、邮箱、URL、密码验证等。
- 工欲善其事,推荐配合可视化调试工具使用,效率更高。
一些常用的正则表达式
1. 手机号(中国)
/^1[3-9]\d{9}$/
2. 固定电话(带区号)
/^0\d{2,3}-?\d{7,8}$/
3. 邮箱地址
/^[\w.-]+@[\w.-]+\.[a-zA-Z]{2,}$/
4. 身份证号(中国第二代)
/^\d{6}(18|19|20)?\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])\d{3}[\dXx]$/
5. 邮政编码(中国)
/^\d{6}$/
6. 用户名(字母开头,4-16位,含字母数字下划线)
/^[a-zA-Z][a-zA-Z0-9_]{3,15}$/
7. 密码(至少包含数字和字母,长度6~20)
/^(?=.*[A-Za-z])(?=.*\d)[A-Za-z\d]{6,20}$/