浅谈正则表达式

处理字符串的瑞士军刀

技术
技术 正则表达式 字符串

2026-03-20

是什么?有什么用?

正则表达式是一种强大的文本模式匹配工具,理解它确实需要系统性地梳理。下面我从基础到进阶,为你详细介绍正则表达式。

正则表达式匹配电子邮箱地址

正则表达式(Regular Expression,简称 regex 或 regexp)是一个描述字符模式的表达式。你可以把它理解为一个高度专业化的“搜索词”,用来在文本中查找、匹配、替换符合特定规则的字符串。

基础匹配

正则表达式的核心由字面字符元字符组成。字面字符就是它自身,比如 a 匹配字母 a;元字符则具有特殊含义。

元字符 含义 示例
. 匹配任意单个字符(除换行符外) a.c 匹配 "abc"、"aac"、"a c"
^ 匹配行的开始 ^Hello 匹配行首的 "Hello"
$ 匹配行的结束 end$ 匹配行尾的 "end"
* 匹配前面的元素零次或多次 ab* 匹配 "a"、"ab"、"abb"
+ 匹配前面的元素一次或多次 ab+ 匹配 "ab"、"abb",不匹配 "a"
? 匹配前面的元素零次或一次 ab? 匹配 "a" 或 "ab"
| 逻辑或 cat|dog 匹配 "cat" 或 "dog"
() 将内部的表达式视为一个整体 (ab)+ 匹配 "ab"、"abab"
[] 字符类,匹配其中任意一个字符 [abc] 匹配 "a"、"b"、"c"
[^] 否定字符类,匹配不在其中的任意一个字符 [^abc] 匹配除 "a"、"b"、"c" 外的任意字符
\ 转义,将元字符转为普通字符 \. 匹配字面点号

反斜杠不仅可以转义字符,还可以简化某些常见的单字符匹配:

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

量词

前面给出的功能足以让我们匹配一种特定的字符串或一类特定的单个字符,但如果我们想要重复这样的匹配呢?Bingo!量词就是为解决这类问题而生的。

量词能够精确控制一种匹配模式重复的次数。

量词 含义
{n} 精确匹配 n 次
{n,} 至少 n 次
{n,m} 至少 n 次,至多 m 次
* 等价于 {0,}
+ 等价于 {1,}
? 等价于 {0,1}

默认情况下,量词是贪婪的——它会尽可能多地匹配。

示例:对于文本 <div>content</div> <div>more</div>

2. 零宽断言

零宽断言匹配的是位置而不是字符,它不消耗文本。

断言 名称 含义
(?=...) 正向先行断言 右侧必须是...
(?!...) 负向先行断言 右侧不能是...
(?<=...) 正向后行断言 左侧必须是...
(?<!...) 负向后行断言 左侧不能是...

示例

3. 捕获与非捕获分组

4. 反向引用

\1\2 等引用之前捕获分组的内容。

示例<(\w+)>.*?</\1> 匹配成对的 HTML 标签,如 <div>content</div>


四、实际应用示例

1. 邮箱验证

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

2. 手机号验证(中国大陆)

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

3. 提取 URL 中的域名

https?://([^/]+)

4. 匹配 IPv4 地址

\b(25[0-5]|2[0-4]\d|1\d{2}|\d{1,2})\.(25[0-5]|2[0-4]\d|1\d{2}|\d{1,2})\.(25[0-5]|2[0-4]\d|1\d{2}|\d{1,2})\.(25[0-5]|2[0-4]\d|1\d{2}|\d{1,2})\b

5. 日期格式(YYYY-MM-DD)

\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])

五、不同语言的差异

正则表达式在不同编程语言中基本语法相同,但细节有差异:

特性 Python JavaScript Java PHP
后行断言 ✅ (3.8+) ✅ (ES2018+)
标志 re.IGNORECASE /i Pattern.CASE_INSENSITIVE /i
匹配方法 re.match / re.search test / exec Matcher.find preg_match

常用标志


六、调试与学习工具


七、常见误区与注意事项

  1. 过度使用正则:对于简单的字符串操作(如 startsWithsplit),直接使用语言内置方法更清晰高效
  2. 性能问题:嵌套量词(如 (a+)+)可能导致灾难性回溯,应避免或改写
  3. 可读性:复杂的正则可以用 x 标志(忽略空白)添加注释,或拆分为多个步骤
  4. 转义混淆:在编程语言字符串中写正则时,反斜杠需要双重转义,如 \\d

八、快速参考卡

功能 表达式
数字 \d
非数字 \D
字母数字 \w
空白 \s
任意字符 .
行首 ^
行尾 $
单词边界 \b
|
分组 ()
任意一个 []
排除 [^]
零次或多次 *
一次或多次 +
零次或一次 ?
精确 n 次 {n}
至少 n 次 {n,}
n 到 m 次 {n,m}

在 Rust 中使用正则式

你的 Rust 标准库并未提供任何关于正则表达式的支持,但是社区生态弥补了这一点。这次我们简要介绍 regex crate 的使用。

在该库中,所有正则表达式都是一个类型为 Regex 的值;为了构建正则表达式,我们需要一个字符串(称为“模式”):

use regex::Regex;

let pat = r"Homer (.)\. Simpson";  // 构建所需的模式
let re = Regex::new(pat).unwrap(); // 用模式构建正则表达式

现在我们可以使用它来

参考资料