🐍
Python3 正则表达式完全指南
编程小白的正则表达式入门与知识点汇总
一、正则表达式基础
正则表达式(Regex)是一种强大的文本处理工具,用于在字符串中进行模式匹配和搜索。就像超级加强版的”查找”功能!
Python中使用正则的步骤
- 导入 re 模块:
import re
- 编译正则表达式:
pattern = re.compile(r'你的模式')
- 使用模式进行匹配或搜索
import re
# 在字符串中查找数字
text = “订单号:12345,日期:2023-08-05”
pattern = re.compile(r’\d+’) # \d+ 表示匹配一个或多个数字
result = pattern.findall(text)
print(result) # 输出: [‘12345’, ‘2023’, ’08’, ’05’]
# 在字符串中查找数字
text = “订单号:12345,日期:2023-08-05”
pattern = re.compile(r’\d+’) # \d+ 表示匹配一个或多个数字
result = pattern.findall(text)
print(result) # 输出: [‘12345’, ‘2023’, ’08’, ’05’]
二、核心元字符
元字符是正则表达式的”特殊功能键”:
- . – 匹配任意单个字符(除了换行符)
- ^ – 匹配字符串的开始位置
- $ – 匹配字符串的结束位置
- * – 匹配前面的子表达式0次或多次
- + – 匹配前面的子表达式1次或多次
- ? – 匹配前面的子表达式0次或1次
- | – 或操作,匹配左边或右边
- \ – 转义特殊字符,例如
\.
匹配点号
# 示例:匹配日期格式 YYYY-MM-DD
date_pattern = re.compile(r’\d{4}-\d{2}-\d{2}’)
# 匹配邮箱地址
email_pattern = re.compile(r'[\w\.-]+@[\w\.-]+\.[a-zA-Z]{2,6}’)
date_pattern = re.compile(r’\d{4}-\d{2}-\d{2}’)
# 匹配邮箱地址
email_pattern = re.compile(r'[\w\.-]+@[\w\.-]+\.[a-zA-Z]{2,6}’)
三、字符类
用于匹配特定类型的字符:
- \d – 匹配任何数字(等价于 [0-9])
- \D – 匹配任何非数字字符
- \w – 匹配任何字母、数字或下划线(等价于 [a-zA-Z0-9_])
- \W – 匹配任何非单词字符
- \s – 匹配任何空白字符(空格、制表符、换行等)
- \S – 匹配任何非空白字符
- [abc] – 匹配a、b或c中的任意一个
- [^abc] – 匹配不在a、b或c中的任意字符
- [a-z] – 匹配a到z之间的任意字符
小技巧:
使用字符类可以匹配特定范围的字符。例如:
[a-zA-Z]
匹配所有大小写字母
[0-9a-fA-F]
匹配十六进制数字
四、量词(重复匹配)
控制匹配字符的数量:
- {n} – 恰好匹配n次
- {n,} – 匹配至少n次
- {n,m} – 匹配n到m次
- *? – 非贪婪匹配(尽可能少匹配)
- +? – 非贪婪匹配(至少一次)
# 贪婪匹配 vs 非贪婪匹配
text = “<h1>标题</h1> <p>段落</p>”
# 贪婪匹配(默认)
greedy_pattern = re.compile(r'<.*>’)
print(greedy_pattern.findall(text)) # 匹配整个字符串
# 非贪婪匹配
non_greedy = re.compile(r'<.*?>’)
print(non_greedy.findall(text)) # 匹配每个标签: [‘<h1>’, ‘</h1>’, ‘<p>’, ‘</p>’]
text = “<h1>标题</h1> <p>段落</p>”
# 贪婪匹配(默认)
greedy_pattern = re.compile(r'<.*>’)
print(greedy_pattern.findall(text)) # 匹配整个字符串
# 非贪婪匹配
non_greedy = re.compile(r'<.*?>’)
print(non_greedy.findall(text)) # 匹配每个标签: [‘<h1>’, ‘</h1>’, ‘<p>’, ‘</p>’]
五、分组与捕获
使用括号 ( )
创建分组:
- ( ) – 捕获分组,可以提取匹配的内容
- (?: ) – 非捕获分组,仅用于分组但不捕获
- (?P<name> ) – 命名捕获分组
# 提取日期中的年、月、日
date_str = “2023-08-05”
date_pattern = re.compile(r'(\d{4})-(\d{2})-(\d{2})’)
match = date_pattern.match(date_str)
if match:
year = match.group(1) # ‘2023’
month = match.group(2) # ’08’
day = match.group(3) # ’05’
# 使用命名分组
named_pattern = re.compile(r'(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2})’)
match = named_pattern.match(date_str)
match.group(‘year’) # ‘2023’
date_str = “2023-08-05”
date_pattern = re.compile(r'(\d{4})-(\d{2})-(\d{2})’)
match = date_pattern.match(date_str)
if match:
year = match.group(1) # ‘2023’
month = match.group(2) # ’08’
day = match.group(3) # ’05’
# 使用命名分组
named_pattern = re.compile(r'(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2})’)
match = named_pattern.match(date_str)
match.group(‘year’) # ‘2023’
六、边界匹配
匹配特定位置而不是具体字符:
- \b – 单词边界
- \B – 非单词边界
- ^ – 字符串开头
- $ – 字符串结尾
# 查找独立的单词”the”
text = “The cat is on the mat, but not on the other.”
pattern = re.compile(r’\bthe\b’, re.IGNORECASE)
results = pattern.findall(text)
print(results) # [‘The’, ‘the’, ‘the’]
# 注意:’other’中的’the’不会被匹配
text = “The cat is on the mat, but not on the other.”
pattern = re.compile(r’\bthe\b’, re.IGNORECASE)
results = pattern.findall(text)
print(results) # [‘The’, ‘the’, ‘the’]
# 注意:’other’中的’the’不会被匹配
七、re模块常用方法
re.match()
– 从字符串开头匹配模式re.search()
– 在整个字符串中搜索第一个匹配项re.findall()
– 查找所有匹配项,返回列表re.finditer()
– 查找所有匹配项,返回迭代器re.sub()
– 替换匹配项re.split()
– 根据模式分割字符串
# 常用方法示例
text = “联系人: 张三, 电话: 13800138000; 李四, 电话: 13900139000”
# 提取所有电话号码
phones = re.findall(r’1[3-9]\d{9}’, text)
# [‘13800138000’, ‘13900139000’]
# 替换敏感信息
safe_text = re.sub(r’1[3-9]\d{4}’, r’****’, text)
# “联系人: 张三, 电话: 138****8000; 李四, 电话: 139****9000”
# 分割联系人信息
contacts = re.split(r'[,;]’, text)
# [‘联系人’, ‘ 张三’, ‘ 电话: 13800138000’, ‘ 李四’, ‘ 电话: 13900139000’]
text = “联系人: 张三, 电话: 13800138000; 李四, 电话: 13900139000”
# 提取所有电话号码
phones = re.findall(r’1[3-9]\d{9}’, text)
# [‘13800138000’, ‘13900139000’]
# 替换敏感信息
safe_text = re.sub(r’1[3-9]\d{4}’, r’****’, text)
# “联系人: 张三, 电话: 138****8000; 李四, 电话: 139****9000”
# 分割联系人信息
contacts = re.split(r'[,;]’, text)
# [‘联系人’, ‘ 张三’, ‘ 电话: 13800138000’, ‘ 李四’, ‘ 电话: 13900139000’]
八、匹配标志(Flags)
修改正则表达式的匹配方式:
re.IGNORECASE
或re.I
– 忽略大小写re.MULTILINE
或re.M
– 多行模式(改变^和$的行为)re.DOTALL
或re.S
– 使.匹配包括换行符在内的所有字符re.VERBOSE
或re.X
– 忽略空白和注释(使正则更易读)
# 标志使用示例
text = “Hello\nWorld”
# 默认情况,. 不匹配换行符
print(re.findall(r’H.*o’, text)) # []
# 使用 DOTALL 标志
print(re.findall(r’H.*o’, text, re.DOTALL)) # [‘Hello\nWo’]
# 使用 VERBOSE 标志创建易读的正则表达式
phone_regex = re.compile(r”’
\d{3,4} # 区号
-? # 可选的连字符
\d{7,8} # 电话号码
”’, re.VERBOSE)
text = “Hello\nWorld”
# 默认情况,. 不匹配换行符
print(re.findall(r’H.*o’, text)) # []
# 使用 DOTALL 标志
print(re.findall(r’H.*o’, text, re.DOTALL)) # [‘Hello\nWo’]
# 使用 VERBOSE 标志创建易读的正则表达式
phone_regex = re.compile(r”’
\d{3,4} # 区号
-? # 可选的连字符
\d{7,8} # 电话号码
”’, re.VERBOSE)
九、正则表达式可视化
理解正则表达式的结构和匹配过程:
正则表达式模式
^
(https?://)
([\w\-\.]+)
(:\d+)?
(/.*)?
$
匹配的URL示例
http://www.example.com
https://sub.domain.com:8080/path
http://localhost:8000
https://example.com/about
上面的正则表达式可以分解为:
^
– 字符串开始(https?://)
– 匹配http://或https://([\w\-\.]+)
– 匹配域名(字母、数字、点、连字符)(:\d+)?
– 可选的端口号(冒号后跟数字)(/.*)?
– 可选的路径(斜杠后跟任意字符)$
– 字符串结束