Python 正则表达式

19.1 正则表达式概念

正则表达式(Regular Expression)是用于匹配字符串模式的强大工具。

应用场景

  • 数据验证(邮箱、电话、密码强度)
  • 文本提取
  • 搜索与替换
  • 日志分析

19.2 基本语法

字符匹配

模式 说明 示例
. 任意字符(除换行) a.c 匹配 “abc”
\d 数字 \d\d 匹配 “12”
\w 字母数字下划线 \w+ 匹配 “hello”
\s 空白字符 a\s b 匹配 “a b”
^ 开头 ^Hello
$ 结尾 World$

示例

1
2
3
4
5
6
7
8
9
10
11
12
import re

text = "Hello 123 World 456"

# 查找数字
print(re.findall(r"\d+", text)) # ['123', '456']

# 查找单词
print(re.findall(r"\w+", text)) # ['Hello', '123', 'World', '456']

# 查找空白
print(re.findall(r"\s+", text)) # [' ', ' ', ' ']

19.3 字符类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import re

# 自定义字符类
print(re.findall(r"[aeiou]", "hello world")) # ['e', 'o', 'o']

# 范围
print(re.findall(r"[a-z]", "Hello 123")) # ['e', 'l', 'l', 'o']
print(re.findall(r"[0-9]", "Hello 123")) # ['1', '2', '3']

# 否定
print(re.findall(r"[^0-9]", "Hello 123")) # ['H', 'e', 'l', 'l', 'o', ' ']

# 组合
print(re.findall(r"[a-zA-Z0-9]", "Hello! 123")) # ['H', 'e', 'l', 'l', 'o', '1', '2', '3']

19.4 量词

量词 说明 示例
* 0 次或多次 ab*c 匹配 “ac”, “abc”, “abbc”
+ 1 次或多次 ab+c 匹配 “abc”, “abbc”
? 0 次或 1 次 ab?c 匹配 “ac”, “abc”
{n} 恰好 n 次 a{3} 匹配 “aaa”
{n,} 至少 n 次 a{2,} 匹配 “aa”, “aaa”
{n,m} n 到 m 次 a{2,4} 匹配 “aa”, “aaa”, “aaaa”

示例

1
2
3
4
5
6
7
import re

text = "a ab abb abbb abbbb"

print(re.findall(r"ab*", text)) # ['a', 'ab', 'abb', 'abbb', 'abbbb']
print(re.findall(r"ab+", text)) # ['ab', 'abb', 'abbb', 'abbbb']
print(re.findall(r"ab{2,3}", text)) # ['abb', 'abbb']

19.5 分组与捕获

基本分组

1
2
3
4
5
6
7
8
9
10
11
import re

text = "2024-11-30"

# 分组提取
match = re.search(r"(\d{4})-(\d{2})-(\d{2})", text)
if match:
print(f"年: {match.group(1)}") # 2024
print(f"月: {match.group(2)}") # 11
print(f"日: {match.group(3)}") # 30
print(f"全部: {match.group(0)}") # 2024-11-30

命名分组

1
2
3
4
5
6
7
8
9
import re

text = "2024-11-30"
match = re.search(r"(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2})", text)

if match:
print(match.group("year")) # 2024
print(match.group("month")) # 11
print(match.group("day")) # 30

非捕获分组

1
2
3
4
5
6
7
import re

# 捕获分组
print(re.findall(r"(abc)+", "abcabc")) # ['abc']

# 非捕获分组
print(re.findall(r"(?:abc)+", "abcabc")) # ['abcabc']

19.6 re 模块常用函数

match() - 从开头匹配

1
2
3
4
5
6
7
8
import re

text = "Hello World"
match = re.match(r"Hello", text)
print(match.group()) # Hello

match = re.match(r"World", text)
print(match) # None(不在开头)

search() - 搜索任意位置

1
2
3
4
5
import re

text = "Hello World"
match = re.search(r"World", text)
print(match.group()) # World

findall() - 查找所有匹配

1
2
3
4
5
6
7
8
import re

text = "Phone: 123-456-7890, Email: test@example.com"
phones = re.findall(r"\d{3}-\d{3}-\d{4}", text)
print(phones) # ['123-456-7890']

emails = re.findall(r"\w+@\w+\.\w+", text)
print(emails) # ['test@example.com']

sub() - 替换

1
2
3
4
5
6
7
8
9
import re

text = "Hello 123 World 456"
result = re.sub(r"\d+", "XXX", text)
print(result) # Hello XXX World XXX

# 限制替换次数
result = re.sub(r"\d+", "XXX", text, count=1)
print(result) # Hello XXX World 456

split() - 分割

1
2
3
4
5
import re

text = "one,two;three four"
result = re.split(r"[,;\s]+", text)
print(result) # ['one', 'two', 'three', 'four']

19.7 编译正则表达式

1
2
3
4
5
6
7
8
9
10
import re

# 预编译(重复使用时更高效)
pattern = re.compile(r"\d{3}-\d{3}-\d{4}")

text1 = "Phone: 123-456-7890"
text2 = "Phone: 987-654-3210"

print(pattern.findall(text1)) # ['123-456-7890']
print(pattern.findall(text2)) # ['987-654-3210']

19.8 实用示例

邮箱验证

1
2
3
4
5
6
7
8
9
import re

def validate_email(email):
pattern = r"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$"
return bool(re.match(pattern, email))

print(validate_email("test@example.com")) # True
print(validate_email("invalid@email")) # False
print(validate_email("user.name@domain.org")) # True

密码强度检查

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import re

def check_password(password):
if len(password) < 8:
return False
if not re.search(r"[A-Z]", password):
return False
if not re.search(r"[a-z]", password):
return False
if not re.search(r"\d", password):
return False
if not re.search(r"[!@#$%^&*]", password):
return False
return True

print(check_password("Abc123!@")) # True
print(check_password("weak")) # False

提取 URL

1
2
3
4
5
import re

text = "Visit https://www.example.com or http://test.org"
urls = re.findall(r"https?://\S+", text)
print(urls) # ['https://www.example.com', 'http://test.org']

19.9 本章小结

  • 正则表达式用于模式匹配和文本处理
  • 常用模式:\d\w\s.^$
  • 量词:*+?{n,m}
  • 分组:() 捕获,(?:) 非捕获,(?P<name>) 命名
  • re 模块:match()search()findall()sub()split()
  • 预编译提高重复使用效率

练习题

  1. 编写正则表达式匹配中国大陆手机号(11 位,1 开头)
  2. 从 HTML 中提取所有 <a> 标签的 href 属性
  3. 验证日期格式 YYYY-MM-DD
  4. 以下代码输出什么?
    1
    2
    import re
    print(re.findall(r"\d+", "a1b2c3"))
ByteFisher
分享编程技术 · 记录钓鱼乐趣
扫码关注
▸ 扫码关注 ◂
Python基础教程 系列
第 19/20 篇
分享: