正则表达式学习
正则表达式(Regular Expression,简称 Regex)是一种用于匹配、查找和替换文本的模式语言,广泛应用于编程(如字符串处理)、文本编辑(如日志分析)、数据验证(如邮箱/手机号格式校验)等场景。掌握正则表达式能极大提升文本处理效率,下面将从基础到进阶系统梳理学习路径。
一、正则表达式核心概念:元字符与匹配规则
正则表达式的核心是“元字符”——具有特殊含义的字符,通过元字符组合成“匹配模式”。先掌握以下基础元字符,再逐步扩展。
1. 基础匹配:匹配普通字符与单个字符
元字符 | 含义 | 示例 | 匹配结果 |
---|---|---|---|
普通字符(a-z/A-Z/0-9) | 匹配字符本身 | abc | 文本中出现的“abc”(如“abc123”中的“abc”) |
. (点) | 匹配任意单个字符(除换行符 \n ) | a.c | “abc”“a1c”“a#c”(不匹配“ac”“a\nc”) |
[] (字符集) | 匹配括号内任意一个字符 | [abc] | “a”“b”“c”(如“a1b2”中的“a”“b”) |
[^] (否定字符集) | 匹配不在括号内的任意一个字符 | [^abc] | “1”“#”“d”(不匹配“a”“b”“c”) |
[a-z] /[A-Z] /[0-9] (范围字符集) | 匹配指定范围的字符 | [0-9a-zA-Z] | 任意数字或字母(即“单词字符”的简化) |
2. 数量匹配:控制字符出现的次数
数量元字符用于指定“前一个字符/子模式”的出现次数,是正则简化写法的关键。
元字符 | 含义 | 示例 | 匹配结果 |
---|---|---|---|
* | 前一个字符出现 0次或多次(贪婪匹配) | a*b | “b”“ab”“aab”“aaab” |
+ | 前一个字符出现 1次或多次(贪婪匹配) | a+b | “ab”“aab”“aaab”(不匹配“b”) |
? | 前一个字符出现 0次或1次 | a?b | “b”“ab”(不匹配“aab”) |
{n} | 前一个字符出现 恰好n次 | a{2}b | “aab”(不匹配“ab”“aaab”) |
{n,} | 前一个字符出现 至少n次 | a{2,}b | “aab”“aaab”(不匹配“ab”) |
{n,m} | 前一个字符出现 n到m次(含n和m) | a{2,3}b | “aab”“aaab”(不匹配“ab”“aaaab”) |
关键:贪婪匹配 vs 非贪婪匹配
- 贪婪匹配(默认):尽可能匹配更多字符。例如
a.*b
匹配“a123b456b”时,会匹配整个“a123b456b”(从第一个“a”到最后一个“b”)。 - 非贪婪匹配:在数量元字符后加
?
,尽可能匹配更少字符。例如a.*?b
匹配“a123b456b”时,会匹配“a123b”(从第一个“a”到最近的“b”)。
3. 位置匹配:匹配文本中的“位置”(无实际字符)
位置元字符不匹配具体字符,而是匹配“字符之间的间隙”,常用于“开头/结尾校验”或“边界匹配”。
元字符 | 含义 | 示例 | 匹配场景 |
---|---|---|---|
^ | 匹配字符串开头(多行模式下匹配行开头) | ^abc | 匹配“abc123”(开头是abc),不匹配“123abc” |
$ | 匹配字符串结尾(多行模式下匹配行结尾) | abc$ | 匹配“123abc”(结尾是abc),不匹配“abc123” |
\b | 匹配单词边界(单词与非单词字符的间隙) | \babc\b | 匹配“abc 123”中的“abc”,不匹配“abc123”(无边界) |
\B | 匹配非单词边界(单词内部的间隙) | a\Bc | 匹配“abc”(a和c之间是单词内部),不匹配“a c”(有空格边界) |
4. 特殊字符与转义
如果需要匹配“元字符本身”(如 .
、*
、?
),需要用 \
进行转义(不同语言中可能需要双重转义,如 Python 中用 \\.
匹配 .
)
特殊字符 | 转义写法 | 示例 | 匹配结果 |
---|---|---|---|
. (点) | \. | a\.b | “a.b”(不匹配“a1b”) |
* (星号) | \* | a\*b | “a*b”(不匹配“aab”) |
( ) (括号) | \( \) | \(abc\) | “(abc)”(不匹配“abc”) |
5. 逻辑与分组:组合多个子模式
通过分组和逻辑元字符,可以将多个简单模式组合成复杂规则。
元字符 | 含义 | 示例 | 匹配结果 |
---|---|---|---|
(...) (分组) | 将括号内的内容视为一个整体(子模式) | (ab)+ | “ab”“abab”“ababab”(匹配多次“ab”) |
` | `(逻辑或) | 匹配“|”前后任意一个模式 | `abc |
\1 \2 (反向引用) | 引用第n个分组的匹配结果 | (ab)\1 | “abab”(\1 代表第一个分组“ab”的结果) |
6. 预定义字符集:简化常用匹配场景
正则提供了预定义的字符集,替代冗长的 []
写法:
预定义字符集 | 等价写法 | 含义 |
---|---|---|
\d | [0-9] | 任意数字 |
\D | [^0-9] | 任意非数字 |
\w | [0-9a-zA-Z_] | 任意单词字符(数字、字母、下划线) |
\W | [^0-9a-zA-Z_] | 任意非单词字符 |
\s | [ \t\n\r\f] | 任意空白字符(空格、制表符、换行符等) |
\S | [^ \t\n\r\f] | 任意非空白字符 |
二、实战场景:正则表达式的典型应用
掌握基础规则后,通过实际场景练习能快速巩固,以下是高频应用案例:
1. 数据验证:校验格式合法性
案例1:校验邮箱格式(简化版)
需求:邮箱需包含 @
和 .
,且 @
后有内容,.
后有2-4个字母(如 .com
、.cn
)。
正则:^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+\.[a-zA-Z]{2,4}$
-
解析:
-
^[a-zA-Z0-9_-]+
:开头是1个以上字母/数字/下划线/横杠(邮箱用户名);
-
-
_
:直接匹配下划线_
-
:直接匹配符号-
;在字符类[]
中,若-
放在末尾或开头,则表示普通符号(若放在中间则表示 “范围”,如a-z
)
-
-
@
:匹配@
符号;[a-zA-Z0-9_-]+
:@
后是1个以上字母/数字/下划线/横杠(邮箱域名前缀,如gmail
);\.[a-zA-Z]{2,4}
:匹配.
加2-4个字母(域名后缀,如.com
);$
:结尾,确保无多余字符。
案例2:校验中国大陆手机号
需求:11位数字,开头为 13
/14
/15
/17
/18
/19
。
正则:^1[345789]\d{9}$
-
解析:
-
^1
:开头是1
;[345789]
:第二位是指定数字;\d{9}
:后续9位数字;$
:结尾,确保共11位。
2. 文本提取:从复杂文本中抓取目标信息
案例:从日志中提取IP地址
日志内容:[2024-05-20 10:30:00] INFO: User from 192.168.1.1 accessed /login
需求:提取IP地址(格式:xxx.xxx.xxx.xxx,每个段0-255)。
正则:\b(?:\d{1,3}\.){3}\d{1,3}\b
-
解析:
-
\d{1,3}
:匹配1-3位数字(IP的一个段);(?:\d{1,3}\.){3}
:非捕获分组((?:...)
,仅用于分组不占用引用),匹配3次“数字+.”(如“192.168.1.”);\d{1,3}
:匹配最后一段数字;\b
:单词边界,避免匹配“192.168.1.1234”这类超长数字。
3. 文本替换:批量修改文本格式
案例:将日期格式从“2024-05-20”改为“2024年05月20日”
正则(匹配原格式):(\d{4})-(\d{2})-(\d{2})
替换为:$1年$2月$3日
(不同语言替换语法可能不同,如 Python 用 \1年\2月\3日
)
-
解析:
-
(\d{4})
:捕获分组1,匹配4位年份;(\d{2})
:捕获分组2/3,分别匹配2位月份和日期;- 替换时用
$1
/$2
/$3
引用分组结果,拼接成新格式。
三、工具与练习:快速提升正则能力
1. 在线测试工具(推荐)
- Regex101(https://regex101.com/):支持多语言(JavaScript、Python、PHP等),实时显示匹配结果,且能解析正则语法(适合新手查错)。
- Regexr(https://regexr.com/):可视化匹配过程,提供预定义字符集、案例库,交互友好。
2. 练习平台
- LeetCode 正则相关题目:如“验证回文串”“正则表达式匹配”(适合结合编程练习)。
- HackerRankRegex 模块(https://www.hackerrank.com/domains/regex):从基础到进阶的阶梯式练习,覆盖匹配、提取、替换等场景。
四、常见误区与注意事项
- 过度依赖复杂正则:简单场景优先用字符串方法(如
startswith()
/endswith()
),复杂场景(如HTML解析)不建议用正则(推荐用专门解析库,如 Python 的BeautifulSoup
)。 - 忽略转义问题:不同语言对
\
的处理不同(如 Python 字符串中\
需转义为\\
,或用原始字符串r""
避免双重转义)。 - 贪婪匹配坑:例如用
^.*\.txt$
匹配“a.txt.bak”时,会匹配整个字符串(因.*
贪婪),需改为非贪婪^.*?\.txt$
才会匹配“a.txt”。 - 多行模式与单行模式:
-
- 多行模式(
m
修饰符):^
/$
匹配每行的开头/结尾(而非整个字符串); - 单行模式(
s
修饰符):.
匹配包括换行符\n
在内的任意字符(默认不匹配)。
- 多行模式(
五、学习路径
- 基础阶段(1-2天):掌握元字符(
.
,[]
,*
,+
,?
,^
,$
)、预定义字符集(\d
,\w
,\s
),能写出简单匹配规则(如匹配数字、字母)。 - 进阶阶段(3-5天):学习分组(
(...)
)、反向引用(\1
)、非贪婪匹配(*?
),练习数据验证(邮箱、手机号)和文本提取(IP、日期)。 - 实战阶段(1-2周):结合实际需求(如日志分析、Excel数据清洗),用工具测试正则,解决真实问题,积累常用正则模板(如提取URL、去除空格)。
正则表达式的核心是“多练+多查”,遇到复杂场景时先拆解需求(如“匹配邮箱”拆分为“用户名+@+域名+后缀”),再逐步组合元字符,配合在线工具调试,很快就能熟练掌握。