Skip to content
encode2026-07-259 分钟阅读

什么是正则表达式

正则表达式(Regular Expression,简称 regex 或 regexp)是一种用于匹配字符串中字符模式的强大工具。它用一套简洁的语法规则,描述复杂的文本搜索、替换和提取需求,是每位开发者都应掌握的核心技能之一。

定义与用途

简单来说,正则表达式是一串字符,它定义了一个搜索模式。你可以用这个模式来:

  • 验证用户输入是否符合格式(邮箱、手机号、密码强度)
  • 从长文本中提取特定信息(URL、日期、数字)
  • 批量替换文本中的某些内容
  • 拆分字符串为有意义的片段
  • 在代码编辑器中进行高级搜索

无论是前端表单验证、后端数据清洗,还是日常文本处理,正则表达式都能大幅提升效率。

历史背景

正则表达式的概念最早可追溯到 20 世纪 50 年代,由数学家 Stephen Kleene 提出。1970 年代,Ken Thompson 将其引入 Unix 系统的 ed 编辑器和 grep 工具中,从此成为程序员的标配工具。如今,几乎所有主流编程语言(JavaScript、Python、Java、Go 等)都内置了正则表达式支持。

正则表达式基础语法

正则表达式的语法虽然看起来像"天书",但核心元素并不多。掌握下面这些基础构件,你就能读懂和编写绝大多数正则表达式。

字面量字符

最基础的正则表达式就是普通字符本身,它们精确匹配自己:

hello

这个模式会匹配字符串中出现的 "hello"。

元字符

元字符是正则表达式中具有特殊含义的字符,它们是构建复杂模式的基石:

| 元字符 | 含义 | |--------|------| | . | 匹配除换行符外的任意单个字符 | | * | 匹配前面的元素零次或多次 | | + | 匹配前面的元素一次或多次 | | ? | 匹配前面的元素零次或一次 | | ^ | 匹配字符串的开头 | | $ | 匹配字符串的结尾 | | \ | 转义字符,让后面的元字符恢复字面含义 | | \| | 或运算,匹配左边或右边的表达式 | | ( ) | 分组,将多个元素组合成一个单元 | | [ ] | 字符类,匹配方括号内的任意一个字符 | | { } | 量词,指定前面元素的匹配次数 |

如果要匹配元字符本身,需要用反斜杠转义,比如 \. 匹配点号,\$ 匹配美元符号。

字符类

字符类用于匹配某一类字符,是最常用的功能之一:

| 字符类 | 含义 | 等价写法 | |--------|------|----------| | \d | 匹配任意数字 | [0-9] | | \w | 匹配字母、数字、下划线 | [a-zA-Z0-9_] | | \s | 匹配空白字符(空格、制表符、换行符等) | [ \t\n\r\f] | | \D | 匹配非数字字符 | [^0-9] | | \W | 匹配非单词字符 | [^a-zA-Z0-9_] | | \S | 匹配非空白字符 | [^ \t\n\r\f] |

你也可以用方括号自定义字符类:

  • [aeiou]:匹配任意一个元音字母
  • [a-z]:匹配任意小写字母
  • [A-Z]:匹配任意大写字母
  • [0-9]:匹配任意数字
  • [^aeiou]:匹配非元音字母(^ 在方括号内表示取反)

量词

量词控制前面的元素应该出现多少次:

| 量词 | 含义 | |------|------| | * | 零次或多次(贪婪) | | + | 一次或多次(贪婪) | | ? | 零次或一次(贪婪) | | {n} | 恰好 n 次 | | {n,} | 至少 n 次 | | {n,m} | n 到 m 次 |

示例:

  • a{3} 匹配 "aaa"
  • \d{4} 匹配四位数字
  • a{2,4} 匹配 2 到 4 个 a
  • a{2,} 匹配至少 2 个 a

锚点

锚点不匹配具体字符,而是匹配位置

| 锚点 | 含义 | |------|------| | ^ | 字符串开头 | | $ | 字符串结尾 | | \b | 单词边界 | | \B | 非单词边界 |

示例:

  • ^Hello 匹配以 "Hello" 开头的字符串
  • world$ 匹配以 "world" 结尾的字符串
  • \bword\b 匹配独立的单词 "word",不会匹配 "sword" 中的 "word"

分组与捕获

用圆括号 ( ) 可以把多个元素组合成一个整体,同时还能捕获匹配的内容供后续使用。

(ab)+

这个模式匹配 "ab" 重复一次或多次,如 "ab"、"abab"、"ababab"。

如果你只需要分组而不需要捕获,可以用非捕获分组

(?:ab)+

(?: ) 表示只分组不捕获,性能略好,也不会占用捕获组编号。

反向引用

捕获的内容可以用 \1\2 等在正则表达式内部引用,数字对应捕获组的顺序:

(\w+)\s+\1

这个模式匹配重复的单词,比如 "hello hello"。\1 引用第一个捕获组匹配的内容。

环视

环视(Lookaround)是一种高级特性,它匹配位置而不消耗字符,分为四种:

| 语法 | 名称 | 含义 | |------|------|------| | (?=...) | 正向前瞻 | 后面必须是 | | (?!...) | 负向前瞻 | 后面必须不是 | | (?<=...) | 正向后顾 | 前面必须是 | | (?<!...) | 负向后顾 | 前面必须不是 |

示例:

  • \d+(?=元) 匹配后面跟着"元"的数字
  • \d+(?!元) 匹配后面不跟着"元"的数字
  • (?<=¥)\d+ 匹配前面是"¥"的数字
  • (?<!¥)\d+ 匹配前面不是"¥"的数字

修饰符(flags)

修饰符改变正则表达式的匹配行为,常用的有:

| 修饰符 | 名称 | 作用 | |--------|------|------| | g | global | 全局匹配,找到所有匹配项而不是第一个 | | i | ignoreCase | 忽略大小写 | | m | multiline | 多行模式,^$ 匹配每行的开头和结尾 | | s | dotAll | 让 . 也能匹配换行符 | | u | unicode | Unicode 模式,正确处理 Unicode 字符 |

在 JavaScript 中,修饰符写在正则字面量的末尾:

const regex = /hello/gi;

常见场景示例

下面是一些实际开发中经常用到的正则表达式模式。

邮箱验证

^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$

这个模式验证标准邮箱格式:用户名@域名.后缀。

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

手机号验证

^1[3-9]\d{9}$

中国大陆手机号验证:以 1 开头,第二位是 3-9,总共 11 位数字。

const phoneRegex = /^1[3-9]\d{9}$/;
phoneRegex.test("13812345678"); // true
phoneRegex.test("12345678901"); // false

URL 匹配

https?:\/\/[^\s]+

匹配 http 或 https 开头的 URL。

const urlRegex = /https?:\/\/[^\s]+/g;
const text = "访问 https://example.com 和 http://test.org 获取更多信息";
text.match(urlRegex);
// ["https://example.com", "http://test.org"]

HTML 标签提取

<(\w+)[^>]*>([\s\S]*?)<\/\1>

匹配成对的 HTML 标签并捕获标签名和内容。

const htmlRegex = /<(\w+)[^>]*>([\s\S]*?)<\/\1>/g;
const html = "<div>Hello <b>World</b></div>";
html.match(htmlRegex);
// ["<div>Hello <b>World</b></div>", "<b>World</b>"]

密码强度校验

至少 8 位,包含大写字母、小写字母和数字:

^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).{8,}$

这里用了三个正向前瞻来分别检查三种字符是否存在。

const passwordRegex = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).{8,}$/;
passwordRegex.test("Abc12345"); // true
passwordRegex.test("abc12345"); // false(缺少大写字母)

正则表达式调试技巧

正则表达式写起来容易出错,掌握调试技巧能帮你少走弯路。

在线测试工具

写正则时,一定要配合在线测试工具实时验证:

  • DevToolkit Pro 正则表达式测试器:实时匹配、语法高亮、匹配信息展示
  • Regex101:详细的正则解释器
  • RegExr:交互式正则学习工具

常见错误与陷阱

1. 忘记转义元字符

想匹配点号却写成了 .,结果匹配了任意字符。记得用 \. 匹配字面量点号。

2. 贪婪匹配导致过度匹配

默认情况下,*+ 是贪婪的,会尽可能多地匹配字符:

<.*>

用这个模式匹配 <div>Hello</div>,会匹配整个字符串而不是第一个标签。解决方法是加 ? 变成非贪婪:

<.*?>

3. 字符类中的元字符

在方括号 [ ] 内,大多数元字符会失去特殊含义。比如 [.] 匹配的就是字面量点号,而不是任意字符。

4. ^$ 的误用

^$ 默认匹配整个字符串的开头和结尾。如果想匹配每行的开头结尾,需要加上 m 修饰符。

性能优化(贪婪 vs 非贪婪)

虽然非贪婪匹配(*?+?)很方便,但在某些场景下性能较差。对于长文本,尽量使用更精确的模式代替非贪婪:

# 性能较差
/<[^>]+>/

# 性能更好
/<[^>]+>/

另外,避免过度使用回溯(backtracking),尤其是嵌套量词的情况,可能导致灾难性回溯(catastrophic backtracking)。

使用 DevToolkit Pro 在线正则表达式测试器

写正则最头疼的就是不断试错。使用 DevToolkit Pro 的在线正则表达式测试器,你可以边写边看匹配结果,大大提升效率。

工具介绍

DevToolkit Pro 正则表达式测试器是一个功能强大的在线工具,支持:

  • 实时匹配:输入正则和测试文本,立即看到匹配结果
  • 语法高亮:匹配到的内容高亮显示,一目了然
  • 捕获组查看:每个捕获组的内容单独展示
  • 匹配信息:显示匹配数量、匹配位置等详细信息
  • 代码生成:一键生成 JavaScript、Python 等语言的代码

实时匹配

在左侧输入你的正则表达式和测试文本,右侧会实时显示:

  • 高亮标记所有匹配项
  • 列出每个匹配的详细信息
  • 展示捕获组内容

无需刷新页面,输入即所得。

flags 切换

工具顶部提供了常用修饰符的快捷开关:

  • g:全局匹配
  • i:忽略大小写
  • m:多行模式
  • s:dotAll 模式
  • u:Unicode 模式

点击即可切换,实时查看效果,不用手动修改正则表达式。

工具优势

  • 纯前端运行:你的正则和测试文本不会上传到服务器,保护隐私
  • 零延迟响应:本地计算,匹配速度极快
  • 语法参考:内置常用正则语法速查表,边写边查
  • 代码导出:一键复制可用的代码片段到你的项目中
  • 完全免费:所有功能免费使用,无次数限制

最佳实践

1. 从简单开始,逐步构建

不要试图一次性写出完美的正则。先写最简单的版本,然后逐步添加约束和边界条件。

2. 保持正则简洁可读

过于复杂的正则表达式是维护噩梦。如果一个正则超过 20 个字符,考虑拆分成多个步骤,或者加上注释。

一些语言支持正则注释,比如 JavaScript 的 x 修饰符(需转义空格),或者用字符串拼接:

const regex = new RegExp(
  "^" +
  "(?=.*[a-z])" +    // 至少一个小写字母
  "(?=.*[A-Z])" +    // 至少一个大写字母
  "(?=.*\\d)" +      // 至少一个数字
  ".{8,}" +
  "$"
);

3. 优先使用内置方法

很多常见需求(邮箱验证、URL 解析)语言或框架已经提供了内置方法。优先使用经过充分测试的标准库,而不是自己写正则。

4. 充分测试边界情况

写好正则后,一定要测试各种边界情况:

  • 空字符串
  • 刚好符合长度的输入
  • 超出长度的输入
  • 特殊字符
  • 空匹配的情况

5. 考虑可读性和可维护性

能工作的正则 ≠ 好的正则。优先选择更易读、更易维护的写法,哪怕稍微长一点。

FAQ

正则表达式和通配符有什么区别?

通配符(如 *?)通常只用于简单的文件名匹配,功能非常有限;而正则表达式是一套完整的模式匹配语言,功能强大得多,可以描述非常复杂的模式。

所有编程语言的正则表达式都一样吗?

基本语法(字符类、量词、锚点等)大致相同,但高级特性(如环视、命名捕获组)的支持程度和具体语法可能有差异。JavaScript、Python、PCRE 是比较常见的流派,使用时注意查阅对应语言的文档。

正则表达式能匹配 HTML 吗?

简单的 HTML 提取可以用正则,但对于复杂的、嵌套的 HTML 结构,正则表达式无法正确处理(因为 HTML 不是正则语言)。正确的做法是使用 HTML 解析器(如浏览器的 DOM API、Python 的 BeautifulSoup 等)。

什么是灾难性回溯?

灾难性回溯(catastrophic backtracking)是指正则表达式在某些输入下需要尝试指数级的匹配路径,导致程序卡死。通常由嵌套的量词(如 (a+)+)引起。避免方法是:尽量减少回溯的可能性,使用更精确的字符类,或者使用原子组(atomic groups)等高级特性。

在线正则测试工具安全吗?

取决于具体工具。很多在线工具会把你的数据发送到服务器处理。如果测试的是敏感数据(如用户隐私、生产环境日志),建议使用纯前端运行的工具。DevToolkit Pro 正则表达式测试器 完全在浏览器本地运行,数据不会上传,可以放心使用。


本文由 DevToolkit Pro 提供。更多开发者工具请访问 首页


ad