正则表达式(Regular Expression,简称 Regex)是处理字符串的“瑞士军刀”。它能用一套特定的语法规则,高效地完成字符串的匹配、查找、替换和提取。在 Python 中,我们通过内置的re模块来使用它。
一、 核心方法:match, search, findall, sub
re模块提供了多个方法,其中最常用的是以下四个。理解它们的区别是掌握正则的第一步。
| 方法 | 功能描述 | 返回值 |
|---|---|---|
re.match | 从字符串开头进行匹配。如果开头不符合规则,则匹配失败。 | 匹配成功返回匹配对象,失败返回None。 |
re.search | 扫描整个字符串,返回第一个匹配成功的结果,找到后即停止。 | 匹配成功返回匹配对象,失败返回None。 |
re.findall | 扫描整个字符串,找到所有匹配项。 | 返回一个包含所有匹配结果的列表,若无匹配则返回空列表[]。 |
re.sub | 搜索字符串,并将所有匹配项替换为指定内容。 | 返回替换后的新字符串。 |
代码示例:
import re s = "lanshis python lanshishujia123anhuiligpython ong" 1. match: 从开头匹配,失败返回 None print(re.match("python", s)) # 输出: None 2. search: 搜索整个字符串,找到第一个就停 result_search = re.search("python", s) print(result_search) # 输出: <re.Match object; span=(8, 14), match='python'> print(result_search.group()) # 输出: python (获取匹配的值) print(result_search.span()) # 输出: (8, 14) (获取匹配的下标) 3. findall: 找到所有匹配项,返回列表 result_findall = re.findall("python", s) print(result_findall) # 输出: ['python', 'python'] 4. sub: 替换所有匹配项 result_sub = re.sub("python", "999", s) print(result_sub) # 输出: lanshis 999 lanshishujia123anhuilig999 ong二、 元字符速查表
元字符是正则表达式的“积木”,掌握它们是构建复杂规则的关键。
1. 单字符匹配
| 元字符 | 功能描述 |
|---|---|
. | 匹配任意一个字符(除了换行符\n)。 |
[] | 匹配[]中列举的任意一个字符,如[abc]匹配 a, b 或 c。 |
\d | 匹配一个数字,等价于[0-9]。 |
\D | 匹配一个非数字字符。 |
\s | 匹配任意空白字符,如空格、Tab 键 (\t)、换行符 (\n) 等。 |
\w | 匹配一个“单词字符”,包括字母、数字和下划线,等价于[a-zA-Z0-9_]。 |
\W | 匹配一个非单词字符。 |
2. 数量词匹配
| 元字符 | 功能描述 |
|---|---|
* | 匹配前一个字符出现0 次或无数次。 |
+ | 匹配前一个字符出现1 次或无数次。 |
? | 匹配前一个字符出现0 次或 1 次。 |
{m} | 匹配前一个字符恰好出现 m 次。 |
{m,} | 匹配前一个字符至少出现 m 次。 |
{m,n} | 匹配前一个字符出现m 到 n 次。 |
3. 边界与分组匹配
| 元字符 | 功能描述 |
|---|---|
^ | 匹配字符串的开头。 |
$ | 匹配字符串的结尾。 |
\b | 匹配一个单词的边界(如空格或标点与字符之间)。 |
\B | 匹配非单词边界。 |
(...) | 将括号内的内容作为一个分组,可以提取或后续引用。 |
(?:...) | 非捕获分组,将括号内内容作为整体处理,但不保存匹配结果,效率更高。 |
三、 实战案例
下面是一些基于上述元字符的常见应用场景。
1. 提取特定类型字符
import re s = "lanshishujai##@@123456python anhui lig gong7&*" 找出所有数字 print(re.findall(r"\d", s)) 输出: ['1', '2', '3', '4', '5', '6', '7'] 找出所有特殊字符(非单词字符) print(re.findall(r"\W", s)) 输出: ['#', '#', '@', '@', ' ', ' ', ' ', ' ', '&', '*'] 找出所有英文字母 print(re.findall(r"[a-zA-Z]", s)) 输出: ['l', 'a', 'n', 's', 'h', 'i', 's', 'h', 'u', 'j', 'a', 'i', ...]2. 验证账号格式
需求:账号只能由字母和数字组成,长度限制在 6 到 10 位。
^: 匹配开头[a-z0-9]: 字符集,匹配小写字母或数字{6,10}: 数量词,匹配前面的字符集 6 到 10 次$: 匹配结尾
s = "abc112233" pattern = r"^[a-z0-9]{6,10}$" print(re.findall(pattern, s)) # 输出: ['abc112233'] (匹配成功)3. 验证 QQ 号格式
需求:纯数字,长度 5-11 位,且第一位不能为 0。
^: 匹配开头[1-9]: 第一位必须是 1-9 的数字[0-9]{4,10}: 后面跟着 4 到 10 位的任意数字(加上第一位,总长度为 5-11 位)$: 匹配结尾
s = "2598144874" pattern = r"^[1-9][0-9]{4,10}$" print(re.findall(pattern, s)) # 输出: ['2598144874'] (匹配成功)4. 提取网页 URL
这是一个相对复杂的例子,用于从文本中提取以http://或https://开头的网址。
text = "配网页地址ssshttps://sc.chinaz.com/tupian/index_1.html配网页地址" 正则表达式解析: http[s]?:// -> 匹配 "http://" 或 "https://" (?: ... )+ -> 非捕获分组,匹配括号内的任意字符一次或多次 [a-zA-Z]|[0-9] -> 匹配字母或数字 [$-_@.&+] -> 匹配 URL 中常见的特殊符号 [!*\(\)] -> 匹配括号等符号(需要转义) (?:%[0-9a-fA-F][0-9a-fA-F]) -> 匹配 URL 编码,如 %20 url_pattern = r"http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\(\)]|(?:%[0-9a-fA-F][0-9a-fA-F]))+" result = re.findall(url_pattern, text) print(result) 输出: ['https://sc.chinaz.com/tupian/index_1.html']四、 小贴士:关于r标记
在定义正则表达式字符串时,强烈建议在字符串前加上r,例如r"\d+"。
这表示一个“原始字符串”(raw string)。在普通字符串中,反斜杠\是转义字符,例如\n代表换行。而在正则中,\d代表数字。如果不加r,Python 会先对\d进行转义,可能导致意料之外的结果。使用r"\d"可以确保反斜杠被原封不动地传递给re模块,避免混淆。