正则表达式(Regular Expression)是一种用来匹配字符串特定模式(match patterns)的强大工具。
它能快速、灵活地(quickly and flexibly)对文本进行搜索、替换、分割(split)等操作,大幅提高处理字符串的效率。
本教程将从正则表达式的基本概念、常用语法到 Python 中的使用方式做详细介绍(a detailed introduction),附带(accompanied by)丰富(rich)示例帮助你更好地掌握。
1. 基本概念 (Basic Concepts)
- 元字符(Metacharacters):在正则表达式中具有特殊意义的字符,如 .、^、$、*、+、?、[]、()、\、| 等
- 量词(Quantifiers):指定(specify)匹配次数的符号,如(e.g) *(匹配 0 次或多次)、+(1 次或多次)、?(0 次或 1 次)、{n}(固定次数)等
2. Python 中的 re 模块 (re Module)
Python 提供了内置的 re 模块来支持正则表达式相关操作,无需额外安装即可使用。
2.1 导入模块 (Importing the Module)
import re #所有正则相关函数都在 re 模块中,例如 re.match(), re.search(), re.findall()
3. 常用函数与用法 (Common Functions & Usage)
3.1 match和search
- re.match(pattern, string):
从字符串开头尝试匹配,若开头部分匹配成功则返回match对象,否则返回 None(Returns a Match object if successful, else None) - re.search(pattern, string):在整个字符串范围内(throughout the string)搜索第一个符合 pattern 的位置。
示例:
import re
text = "晚饭吃火锅"
m1 = re.match(r"晚饭", text)
m2 = re.search(r"吃", text)
m3 = re.match(r"火锅",text)
print("match:", m1) # 因为句子开头就是"晚饭",所以匹配成功
print("search:", m2) # 句子里面有"吃",同样也能匹配成功
print("match:",m3) #返回None
3.2 re.findall() 和 re.finditer()
- re.findall(pattern, string):返回所有不重叠匹配的列表(non-overlapping matches)。
- re.finditer(pattern, string):返回一个可迭代对象,每个元素是一个 Match。
示例:
import re
text = "邮箱:abc@mail.com,另一个邮箱:xyz@mail.com"
emails = re.findall(r"[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}", text)
print(emails) # ['abc@mail.com', 'xyz@mail.com']
邮箱匹配解释:
- [a-zA-Z0-9._%+-]+这部分用于匹配电子邮件地址的用户名部分, 即@符号之前的部分
- 匹配一个或多个字母(大小写)、数字、点(.)、下划线(_)、百分号(%)、加号(+)或减号(-),最后的+号表示前面的元素必须出现 1 次或多次
- @[a-zA-Z0-9.-]+这部分用于匹配电子邮件地址的域名部分(即 @ 符号之后的部分)。域名通常由字母、数字、点或减号组成,如sub.domain.co.uk
- \.匹配一个点(.)。在正则表达式中,点(.)是一个特殊字符,表示匹配任意单个字符。因此,需要用反斜杠(\)对其进行转义,使其表示字面上的点
- [a-zA-Z]{2,} 匹配两个或更多字母(大小写), 这部分用于匹配顶级域名(TLD),如 .com、.org、.net 等。顶级域名通常由两个或更多字母组成
3.3 re.sub() 和 re.split()
- re.sub(pattern, repl, string):用 repl 替换字符串中符合 pattern 的部分,并返回替换后的结果。
- re.split(pattern, string):按照匹配到的 pattern 分割字符串,返回列表。
示例:
import re
# 替换示例
原句 = "咖啡好喝,奶茶好喝,酒好喝"
新句 = re.sub("好喝", "不好喝", 原句)
print(新句) #输出"咖啡不好喝,奶茶不好喝,酒不好喝"
# 分割示例
长句 = "他是个饭桶,不会做饭,只会洗碗"
短句 = re.split(",", 长句)
print(短句) #输出 ['他是个饭桶', '不会做饭', '只会洗碗']
4. 正则表达式语法要点 (Key Regex Syntax)
语法 | 含义 | 示例 |
. | 匹配除换行符外的任意字符 | a.b 可匹配 "axb"、"a9b" 等 |
^ / $ | 匹配字符串的开头 / 结尾 | ^abc 匹配 "abc..." |
* | 匹配前一个表达式 0 次或多次 | ab* 可匹配 "a", "ab", "abb" 等 |
+ | 匹配前一个表达式 1 次或多次 | ab+ 可匹配 "ab", "abb" 等 |
? | 匹配前一个表达式 0 次或 1 次 | ab? 可匹配 "a" 或 "ab" |
{n,m} | 匹配前一个表达式 n~m 次 | ab{1,3} 可匹配 "ab", "abb", "abbb" |
[] | 字符类,匹配方括号内任意一个字符 | [abc] 匹配 "a", "b", 或 "c" |
[^...] | 非字符类,匹配不在括号内的字符 | [^0-9] 匹配任何非数字字符 |
` | ` | 或运算,匹配符号两边任意一个表达式 |
() | 分组,匹配并捕获组内容 | (ab)+ 匹配 "ab", "abab", "ababab" |
\d / \w | 匹配数字 / 匹配字母数字下划线 | \d 相当于 [0-9], \w 相当于 [A-Za-z0-9_] |
\s | 匹配任意空白字符 (空格、制表符等) | \s+ 匹配一个或多个空白 |
5. 编译正则表达式 (Compiling Regex)
使用 re.compile(pattern, flags=0) 可以预编译正则表达式,提高多次重复匹配的效率,并可指定模式修饰符(如 re.IGNORECASE)。
import re
# 入门示例
模式 = re.compile(r"hello", re.IGNORECASE) #忽略大小写
result = 模式.search("HELLo这个精彩的世界")
print(result) # 匹配成功
# 验证电话号
号码模式 = re.compile(r"^1\d{10}$") #表示1开头,数字结尾,总共11位数字
所有号码 = ["13912345678", "12345", "18888888888"]
for 号 in 所有号码:
print(号, "->", bool(号码模式.match(号)))
# 验证邮箱
邮箱模式 = re.compile(r"^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$")
所有邮箱 = ["abc@mail.com", "test123@domain.co", "invalid@.com"]
for 邮 in 所有邮箱:
print(邮, "->", bool(邮箱模式.match(邮)))
6. 小贴士与注意事项 (Tips & Caveats)
- 注意转义:在正则中,\ 具有特殊意义,如需匹配反斜杠本身需写 \\。
- 调试技巧:可以使用在线正则测试工具或 re.DEBUG 标志调试表达式。
- 避免滥用:正则虽强大,但处理复杂逻辑或嵌套结构时可读性不佳,应量力而行。
(Regex is powerful but can become unreadable if overused for complex logic.)
熟练运用正则表达式后,你将能在文本处理、数据清洗、日志分析等领域如鱼得水