正则表达式:从入门到精通

正则表达式(Regular Expression,简称Regex) 是一种强大的文本处理工具,用于在字符串中匹配、查找、替换特定模式的文本。本教程将从零开始,带你系统掌握这项核心技能。

本文档pdf版本下载

第一部分:基础入门

1.1 什么是正则表达式?

正则表达式是一个模式字符串 ,描述了一类文本的共同特征 。就像用"通配符"*.txt匹配所有文本文件一样,但功能强大百倍。

实际应用场景:

  • 验证用户输入(邮箱、手机号、密码强度)
  • 提取网页中的数据(爬虫)
  • 批量文本处理(查找替换)
  • 日志分析
  • 代码重构

1.2 你的第一个正则表达式

最简单的模式:字面匹配

复制代码
hello
  • 匹配字符串中完全包含 "hello"的部分

  • 示例:"hello world"→ 匹配到 "hello"

  • 默认区分大小写,"Hello"不匹配

在线工具推荐(边学边练):

第二部分:元字符与字符类(核心基础)

2.1 特殊字符(元字符)

这些字符在正则中有特殊含义:

元字符 含义 示例 匹配
. 匹配任意单个字符(除换行符) a.c "abc", "a2c", "a c"
\d 数字(等价于[0-9] \d\d "12", "45"
\w 单词字符(字母、数字、下划线) \w+ "hello", "user_123"
\s 空白字符(空格、制表符、换行) a\sb "a b"
\D 非数字 \D+ "abc", "---"
\W 非单词字符 \W "@", " "
\S 非空白字符 \S+ "hello"

2.2 自定义字符类

[]定义你想匹配的字符集合:

表达式 含义 匹配示例 不匹配
[abc] 匹配a、b、c中的任意一个 "a", "b" "d"
[a-z] 匹配a到z的任意小写字母 "c", "m" "A", "1"
[A-Za-z] 匹配任意大小写字母 "a", "Z" "1", "_"
[0-9] 匹配数字(同\d "5" "a"
[^abc] 否定 :匹配不是a、b、c的字符 "d", "1" "a", "b"
[a-zA-Z0-9_] 匹配单词字符(同\w "a", "1", "_" "@"

实用示例:

复制代码
# 匹配16进制颜色值(如#FF00FF)
#[0-9A-Fa-f]{6}

# 匹配中文字符(在支持Unicode的环境中)
[\u4e00-\u9fa5]

第三部分:量词与重复(控制匹配次数)

3.1 基本量词

量词 含义 示例 匹配
* 匹配0次或多次(尽可能多) a* "", "a", "aaaa"
+ 匹配1次或多次(尽可能多) \d+ "1", "123"
? 匹配0次或1次(可有可无) colou?r "color", "colour"
{n} 匹配恰好n次 \d{4} "2024"(4位数字)
{n,} 匹配至少n次 \w{3,} "hello", "abc123"(至少3个)
{n,m} 匹配n到m次 \d{2,4} "12", "1234"

3.2 贪婪 vs 懒惰(非贪婪)模式

这是正则表达式的核心难点,必须掌握!

复制代码
# 示例文本
"<div>内容1</div><div>内容2</div>"

# 1. 贪婪模式(默认):尽可能多地匹配
<.*>        # 匹配结果:"<div>内容1</div><div>内容2</div>"
            # 匹配了整个字符串,因为.*会吃到最后一个>才停止

# 2. 懒惰模式(加?):尽可能少地匹配
<.*?>       # 匹配结果:第一次"<div>",第二次"</div>",第三次"<div>",第四次"</div>"
            # 遇到第一个>就停止匹配

所有量词都有对应的懒惰版本:

  • *?+???{n,}?{n,m}?

第四部分:分组、分支与引用

4.1 分组 ()

用小括号()将模式分组:

复制代码
# 分组示例
(ab)+        # 匹配:"ab", "ababab"(ab重复)
(gr(a|e)y)   # 匹配:"gray" 或 "grey"

分组的作用:

  1. 量化重复(ab){3}"ababab"

  2. 多选分支gray|grey可写作 gr(a|e)y

  3. 捕获文本:用于提取或替换

4.2 分支 |

相当于逻辑"或":

复制代码
# 匹配多种可能性
cat|dog|fish     # 匹配"cat"或"dog"或"fish"
gr(a|e)y         # 匹配"gray"或"grey"

# 注意范围:会匹配整个左侧或右侧
^I like (cats|dogs)\.$  # 匹配"I like cats." 或 "I like dogs."

4.3 引用分组

\1\2等引用前面捕获的分组:

复制代码
# 匹配重复的单词
(\w+) \1          # 匹配:"hello hello", "the the"
                  # \1代表第一个分组匹配到的内容

# 匹配成对的HTML标签
<(\w+)>.*?</\1>   # 匹配:<div>内容</div> 但不匹配 <div>内容</span>
                  # \1确保结束标签与开始标签同名

第五部分:锚点与边界(精确定位)

5.1 常用锚点

锚点 含义 示例 匹配位置
^ 字符串开始(多行模式下行首) ^Hello 必须以Hello开头
$ 字符串结束(多行模式下行尾) world$ 必须以world结尾
\b 单词边界(\w和\W之间) \bcat\b 单独的"cat",不匹配"category"
\B 非单词边界 \Bcat\B "scattered"中的"cat"
(?=...) 正向肯定预查 Windows(?=10) 匹配后面是"10"的"Windows"
(?!...) 正向否定预查 Windows(?!10) 匹配后面不是"10"的"Windows"
(?<=...) 反向肯定预查 (?<=\$)\d+ 匹配前面是"$"的数字
(?<!...) 反向否定预查 (?<!\$)\d+ 匹配前面不是"$"的数字

实用示例:

复制代码
# 验证整个字符串是6位数字
^\d{6}$

# 查找单词"the"(不匹配"there")
\bthe\b

# 匹配金额数字(不带$符号)
(?<=\$)\d+\.\d{2}  # 匹配:"$123.45"中的"123.45"

# 匹配不以"test_"开头的变量名
^(?!test_)\w+

第六部分:标志/修饰符(修改匹配行为)

在大多数编程语言中,正则表达式可以添加标志:

标志 含义 示例
i 忽略大小写 /hello/i匹配"Hello"、"HELLO"
g 全局匹配(查找所有) 默认只匹配第一个,g标志匹配所有
m 多行模式 ^$匹配每行的开头结尾
s 单行模式 .匹配包括换行符的所有字符
u Unicode模式 正确处理Unicode字符

使用示例(JavaScript):

javascript 复制代码
// 不区分大小写 + 全局匹配
const regex = /hello/gi;
"Hello world, hello everyone".match(regex); // ["Hello", "hello"]

第七部分:实战应用(经典场景)

7.1 验证类

复制代码
# 邮箱(简单版)
^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$

# 中国大陆手机号
^1[3-9]\d{9}$

# 身份证号(18位)
^\d{17}[\dXx]$

# 日期(YYYY-MM-DD)
^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])$

# 强密码(8-20位,含大小写字母、数字、特殊字符)
^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,20}$

7.2 提取类

复制代码
# 提取HTML标签内容
<tag[^>]*>(.*?)</tag>

# 提取URL中的域名
https?://([^/]+)

# 提取CSV字段
"([^"]*)"|([^,]+)  # 处理带/不带引号的字段

# 提取所有中文
[\u4e00-\u9fa5]+

7.3 替换类

复制代码
# 删除HTML标签
<[^>]*>

# 删除多余空白行
\n\s*\n

# 格式化电话号码(10位)
(\d{3})(\d{4})(\d{4})  →  $1-$2-$3

第八部分:性能优化与最佳实践

8.1 效率优化技巧

  1. 减少回溯 :避免(.*)*这样的嵌套量词

  2. 使用具体字符类 :用[a-z]代替.*?中的?

  3. 避免捕获分组 :用(?:...)非捕获分组

  4. 尽早失败:在开头使用锚点或具体字符

  5. 懒惰匹配要谨慎.*?可能导致大量回溯

8.2 最佳实践

  1. 注释复杂正则

    (?x) # 启用注释模式
    ^(\d{4}) # 年
    -(\d{2}) # 月
    -(\d{2}) # 日
    $

  2. 测试驱动开发

    • 准备测试用例(包括边界情况)

    • 使用在线工具逐步调试

    • 编写单元测试

  3. 可读性优先

    不好

    ^\d{4}-\d{2}-\d{2}$

    更好(带分组命名)

    ^(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})$

第九部分:各语言差异速查

功能 JavaScript Python Java PHP
创建正则 /pattern/flags re.compile(r"pattern", flags) Pattern.compile("pattern") /pattern/flags
忽略大小写 i re.IGNORECASE Pattern.CASE_INSENSITIVE i
多行模式 m re.MULTILINE Pattern.MULTILINE m
全局匹配 g 默认全局 默认全局 g
命名分组 (?<name>...) (?P<name>...) (?<name>...) (?P<name>...)

第十部分:调试与工具

10.1 调试步骤

  1. 明确需求:精确描述你要匹配什么

  2. 分步构建:从简单到复杂逐步添加

  3. 测试用例:包括应该匹配和不应该匹配的例子

  4. 优化性能:检查是否有回溯问题

10.2 推荐工具

  • Regex101:交互式测试,有详细解释

  • RegExr:实时高亮,支持社区分享

  • Regex Tester:VSCode插件,集成开发环境

  • Debuggex:可视化正则表达式

结语

正则表达式是实践出真知的技能。建议你:

  1. 从简单的模式开始,逐步增加复杂度

  2. 为每个正则写测试用例,包括边界情况

  3. 理解原理,不要死记硬背

  4. 收藏本教程,遇到问题时快速查阅

练习是最好的老师,现在打开Regex101,从最简单的模式开始尝试吧!

相关推荐
网安2311石仁杰2 小时前
深入解析OWASP ZAP:从软件工程视角看安全扫描器的架构设计
java·安全·软件工程
bbq粉刷匠2 小时前
Java--多线程--线程安全3
java·开发语言
霍格沃兹测试学院-小舟畅学2 小时前
LangChain + DeepSeek 实战拆解:从 LCEL 到智能体,如何真正“做出”一个可控 AI 系统?
java·人工智能·langchain
Promising_GEO2 小时前
探索Python融合地学:绘制栅格数据经纬度剖面图
开发语言·python·遥感·地理
96772 小时前
java数据类型解析以及相关八股文的题 String 到底是基本类型还是引用类型?
java·开发语言·python
瞎某某Blinder2 小时前
DFT学习记录[5]电子结构分析+光学分析
linux·python·科技·学习·生活·matplotlib·帅哥
困死,根本不会2 小时前
蓝桥杯 Python 备考全攻略:从入门到进阶的学习路线
笔记·python·学习·算法·蓝桥杯
yuyu_03042 小时前
AI识别手部异常
python·ai
码界奇点2 小时前
基于Java GUI和Access数据库的图书馆管理系统设计与实现
java·开发语言·数据库·毕业设计·源代码管理