- p216 正则表达式
一、基础语法:字符与规则
1. 普通字符
- 直接匹配自身,比如
abc
会精准匹配字符串里的"abc"
子串,像在"xyzabc123"
里,abc
就能匹配到中间的"abc"
。
2. 元字符(核心规则)
元字符 | 含义 & 示例 |
---|---|
. |
匹配除换行符(\n 等)外的任意单个字符。例:a.c 可匹配 "abc" 、"a&c" ,但不匹配 "a\nc"
|
[] |
匹配方括号内任意单个字符。例:[abc] 匹配 "a" /"b" /"c" ;[a-z] 匹配任意小写字母(范围) |
[^] |
匹配不在方括号内的任意单个字符(取反)。例:[^0-9] 匹配非数字字符,像字母、符号等 |
\d |
等价于 [0-9] ,匹配数字
|
\D |
等价于 [^0-9] ,匹配非数字
|
\w |
等价于 [a-zA-Z0-9_] ,匹配字母、数字、下划线(“单词字符”) |
\W |
等价于 [^a-zA-Z0-9_] ,匹配非单词字符(如符号 !@# 等) |
\s |
匹配空白字符(空格、制表符 \t 、换行符 \n 等) |
\S |
匹配非空白字符 |
^ |
匹配字符串的开头位置(多行模式下也匹配行首)。例:^abc 只匹配字符串以 "abc" 开头的部分 |
$ |
匹配字符串的结尾位置(多行模式下也匹配行尾)。例:abc$ 只匹配字符串以 "abc" 结尾的部分 |
| |
逻辑“或”,匹配左边或右边的子模式。例:abc|123 匹配 "abc" 或 "123"
|
() |
分组,把多个字符当一个整体匹配,也用于捕获匹配结果(提取子串)。例:(abc)+ 匹配连续的 "abcabc"
|
* |
匹配前面的子模式 0 次或多次(尽可能多匹配,“贪婪模式”)。例:a* 匹配 "" (空)、"a" 、"aa"
|
+ |
匹配前面的子模式 1 次或多次(贪婪)。例:a+ 匹配 "a" 、"aa" ,但不匹配 ""
|
? |
有两种用法: 1. 匹配前面的子模式 0 次或 1 次(可选),例: a? 匹配 "" 或 "a" 2. 跟在 * /+ 后,开启非贪婪模式(尽可能少匹配),例:a+? 匹配到单个 "a" 就停止 |
{n} |
匹配前面的子模式恰好 n 次。例:a{3} 匹配 "aaa"
|
{n,} |
匹配前面的子模式至少 n 次(贪婪)。例:a{2,} 匹配 "aa" 、"aaa" 等 |
{n,m} |
匹配前面的子模式 n 到 m 次(贪婪)。例:a{1,3} 匹配 "a" 、"aa" 、"aaa"
|
二、常见场景示例
1. 验证字符串格式(如邮箱、手机号)
-
验证邮箱(简单版,实际更复杂):
^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$
解释:
-
^
开头,$
结尾 → 匹配完整字符串; -
[a-zA-Z0-9_.+-]+
→ 匹配邮箱用户名(字母、数字、_
/.
/+
/-
等); -
@
→ 固定符号; -
[a-zA-Z0-9-]+
→ 匹配域名(如gmail
、baidu
); -
\.
→ 转义.
(因为.
本身是元字符,需匹配实际点号); -
[a-zA-Z0-9-.]+
→ 匹配后缀(如com
、cn
、co.uk
)。
-
-
验证手机号(以中国大陆手机号为例):
^1[3-9]\d{9}$
解释:
-
^1
→ 以1
开头; -
[3-9]
→ 第二位是 3 - 9 的数字; -
\d{9}
→ 后面跟 9 位数字; -
$
→ 结尾,确保整体是 11 位手机号。
-
2. 提取关键信息(如从日志里抓 ID)
假设日志格式是:[INFO] 2024-10-01 12:00:00 - user_id=12345, action=login
想提取 user_id
的值,可用 regex:
user_id=(\d+)
-
user_id=
→ 匹配固定文本; -
(\d+)
→ 分组捕获数字(\d+
匹配 1 个及以上数字),提取结果就是12345
。
3. 替换文本(如清理非法字符)
把字符串里的“非字母、数字、下划线”替换成空格,可用:
import re
text = "hello!@# world_123"
new_text = re.sub(r'[^a-zA-Z0-9_]', ' ', text)
# new_text 结果: "hello world_123"(!@# 被换成空格)
-
re.sub()
是 Pythonre
模块的替换函数; -
[^a-zA-Z0-9_]
→ 匹配非字母、数字、下划线的字符; - 第二个参数
' '
表示用空格替换匹配到的内容。
三、Python 中使用正则(re
模块核心用法)
Python 通过 re
模块实现正则功能,常用方法:
1. re.match(pattern, string)
- 尝试从字符串开头匹配 pattern,匹配到返回
Match
对象,否则返回None
。 - 示例:
import re result = re.match(r'abc', 'abcdef') if result: print(result.group()) # 输出: abc(匹配到的内容)
2. re.search(pattern, string)
- 扫描整个字符串,找第一个匹配的子串,返回
Match
对象或None
。 - 示例:
result = re.search(r'\d+', 'abc123def456') if result: print(result.group()) # 输出: 123(第一个数字串)
3. re.findall(pattern, string)
- 找到所有匹配的子串,返回列表(若有分组,返回分组内容列表)。
- 示例:
result = re.findall(r'\d+', 'abc123def456') print(result) # 输出: ['123', '456']
4. re.sub(pattern, repl, string, count=0)
- 替换匹配的子串,
repl
可以是字符串或函数;count
控制替换次数(0 表示全部替换)。 - 示例(替换所有数字为
#
):new_text = re.sub(r'\d+', '#', 'abc123def456') print(new_text) # 输出: abc#def#
5. re.compile(pattern)
- 预编译正则表达式,提升重复匹配效率(频繁用同个 pattern 时推荐)。
- 示例:
pattern = re.compile(r'\d+') result1 = pattern.findall('abc123') result2 = pattern.findall('def456') print(result1, result2) # 输出: ['123'] ['456']
四、写正则的小技巧
- 先拆分需求:把复杂匹配拆成小规则(如邮箱拆成“用户名 + @ + 域名 + 后缀” )。
- 巧用在线工具调试:像 Regex101 ,输入 pattern 和测试文本,实时看匹配结果,还能解释正则含义,超方便~
-
注意贪婪/非贪婪:
*
/+
默认贪婪(尽可能多匹配),加?
可转非贪婪(a+?
匹配到单个a
就停),处理多行、短文本时容易踩坑,需留意。
正则表达式乍看复杂,但记住常用元字符含义,结合场景练习(比如验证自己的手机号、邮箱格式 ),很快就能上手啦!遇到复杂需求,分步拆解 + 在线调试,基本都能搞定~