Python3 【正则表达式】:经典示例参考手册
文章摘要
本文由两部分组成:
- 基础速通:浓缩知识点,干货满满;
- 经典示例:15 个经典示例,便于模仿学习。
一、基础速通
正则表达式(Regular Expression,简称 regex 或 regexp)是一种强大的工具,用于匹配和处理文本。Python 通过 re
模块提供了对正则表达式的支持。正则表达式可以用于搜索、替换、分割和验证字符串。
1. 基本概念
- 模式(Pattern):正则表达式的核心是模式,它定义了你要匹配的文本规则。
- 元字符(Metacharacters):在正则表达式中具有特殊意义的字符,如
.
,*
,+
,?
,^
,$
,\
,|
,{
,}
,[
,]
,(
,)
等。 - 普通字符:除了元字符之外的字符,如字母、数字等。
2. 常用元字符
.
:匹配除换行符以外的任意单个字符。^
:匹配字符串的开头。$
:匹配字符串的结尾。*
:匹配前面的字符零次或多次。+
:匹配前面的字符一次或多次。?
:匹配前面的字符零次或一次。{n}
:匹配前面的字符恰好 n 次。{n,}
:匹配前面的字符至少 n 次。{n,m}
:匹配前面的字符至少 n 次,至多 m 次。\
:转义字符,用于匹配元字符本身。|
:或操作符,匹配左边或右边的表达式。[]
:字符集,匹配其中的任意一个字符。()
:分组,将多个字符作为一个整体进行匹配。
3. 常用字符集
\d
:匹配任意数字,等价于[0-9]
。\D
:匹配任意非数字字符,等价于[^0-9]
。\w
:匹配任意字母、数字或下划线,等价于[a-zA-Z0-9_]
。\W
:匹配任意非字母、数字或下划线的字符,等价于[^a-zA-Z0-9_]
。\s
:匹配任意空白字符,包括空格、制表符、换行符等。\S
:匹配任意非空白字符。
4. re
模块常用函数
re.match(pattern, string)
:从字符串的起始位置匹配正则表达式,如果匹配成功返回匹配对象,否则返回None
。re.search(pattern, string)
:在字符串中搜索匹配正则表达式的第一个位置,如果匹配成功返回匹配对象,否则返回None
。re.findall(pattern, string)
:返回字符串中所有匹配正则表达式的子串,返回一个列表。re.finditer(pattern, string)
:返回一个迭代器,包含所有匹配正则表达式的子串。re.sub(pattern, repl, string)
:将字符串中匹配正则表达式的部分替换为repl
。re.split(pattern, string)
:根据正则表达式匹配的子串将字符串分割,返回一个列表。
5. 示例
5.1 匹配数字
import re
text = "The price is 123.45 dollars."
pattern = r'\d+\.\d+'
match = re.search(pattern, text)
if match:
print("Found:", match.group())
5.2 替换字符串
import re
text = "Hello, world!"
pattern = r'world'
repl = 'Python'
new_text = re.sub(pattern, repl, text)
print(new_text) # 输出: Hello, Python!
5.3 分割字符串
import re
text = "apple,banana,cherry"
pattern = r','
result = re.split(pattern, text)
print(result) # 输出: ['apple', 'banana', 'cherry']
5.4 查找所有匹配
import re
text = "The rain in Spain falls mainly in the plain."
pattern = r'\bin\b'
matches = re.findall(pattern, text)
print(matches) # 输出: ['in', 'in', 'in']
6. 分组和捕获
分组使用 ()
来定义,可以捕获匹配的子串。
import re
text = "John Doe, Jane Doe"
pattern = r'(\w+) (\w+)'
matches = re.findall(pattern, text)
for first_name, last_name in matches:
print(f"First: {first_name}, Last: {last_name}")
7. 非贪婪匹配
默认情况下,*
和 +
是贪婪的,会尽可能多地匹配字符。可以在它们后面加上 ?
来使其变为非贪婪匹配。
import re
text = "<html><head><title>Title</title></head></html>"
pattern = r'<.*?>'
matches = re.findall(pattern, text)
print(matches) # 输出: ['<html>', '<head>', '<title>', '</title>', '</head>', '</html>']
8. 编译正则表达式
如果需要多次使用同一个正则表达式,可以将其编译为正则表达式对象,以提高效率。
import re
pattern = re.compile(r'\d+')
text = "There are 3 apples and 5 oranges."
matches = pattern.findall(text)
print(matches) # 输出: ['3', '5']
9. 标志(Flags)
re
模块提供了一些标志来修改正则表达式的行为,如忽略大小写、多行匹配等。
re.IGNORECASE
或re.I
:忽略大小写。re.MULTILINE
或re.M
:多行模式,^
和$
匹配每行的开头和结尾。re.DOTALL
或re.S
:使.
匹配包括换行符在内的所有字符。
import re
text = "Hello\nWorld"
pattern = r'^world'
match = re.search(pattern, text, re.IGNORECASE | re.MULTILINE)
if match:
print("Found:", match.group())
10. 小结
正则表达式是处理文本的强大工具,Python 的 re
模块提供了丰富的功能来支持正则表达式的使用。通过掌握正则表达式的基本语法和 re
模块的常用函数,你可以高效地处理各种文本匹配和替换任务。
二、经典示例
以下是 15 个经典的正则表达式应用实例,每个实例都包含正则表达式的解释、测试代码以及执行结果的注释说明。
1. 匹配邮箱地址
正则表达式: r'^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$'
- 解释:匹配常见的邮箱地址格式。
^
和$
表示字符串的开始和结束。[a-zA-Z0-9_.+-]+
匹配用户名部分。@
匹配邮箱中的@
符号。[a-zA-Z0-9-]+
匹配域名部分。\.
匹配域名中的点.
。[a-zA-Z0-9-.]+
匹配顶级域名部分。
import re
pattern = r'^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$'
emails = ["[email protected]", "[email protected]", "invalid-email@com"]
for email in emails:
if re.match(pattern, email):
print(f"Valid: {email}")
else:
print(f"Invalid: {email}")
# 执行结果:
# Valid: [email protected]
# Valid: [email protected]
# Invalid: invalid-email@com
2. 匹配手机号码
正则表达式: r'^1[3-9]\d{9}$'
- 解释:匹配中国大陆的手机号码。
1
表示手机号码的第一位。[3-9]
表示第二位可以是 3 到 9 之间的数字。\d{9}
表示后面跟着 9 位数字。
import re
pattern = r'^1[3-9]\d{9}$'
phones = ["13800138000", "12345678901", "19912345678"]
for phone in phones:
if re.match(pattern, phone):
print(f"Valid: {phone}")
else:
print(f"Invalid: {phone}")
# 执行结果:
# Valid: 13800138000
# Invalid: 12345678901
# Valid: 19912345678
3. 匹配 URL
正则表达式: r'https?://(?:www\.)?\S+'
- 解释:匹配 HTTP 或 HTTPS 协议的 URL。
https?
匹配http
或https
。://
匹配 URL 中的协议分隔符。(?:www\.)?
匹配可选的www.
。\S+
匹配 URL 的其余部分。
import re
pattern = r'https?://(?:www\.)?\S+'
urls = ["https://www.example.com", "http://example.com", "ftp://example.com"]
for url in urls:
if re.match(pattern, url):
print(f"Valid: {url}")
else:
print(f"Invalid: {url}")
# 执行结果:
# Valid: https://www.example.com
# Valid: http://example.com
# Invalid: ftp://example.com
4. 匹配日期(YYYY-MM-DD)
正则表达式: r'^\d{4}-[01]?[0-2]-[0123]?[0-9]$'
- 解释:匹配
YYYY-MM-DD
格式的日期。 \d{4}
匹配 4 位年份。-
匹配日期分隔符。[01]?[0-2]
匹配 2 位月份。[0123]?[0-9]
匹配 2 位日期。
import re
pattern = r'^\d{4}-[01]?[0-2]-[0123]?[0-9]$'
dates = ["2023-10-05", "2023/10/05", "2023-13-01"]
for date in dates:
if re.match(pattern, date):
print(f"Valid: {date}")
else:
print(f"Invalid: {date}")
# 执行结果:
# Valid: 2023-10-05
# Invalid: 2023/10/05
# Invalid: 2023-13-01
5. 匹配 IP 地址
正则表达式: r'^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$'
- 解释:匹配 IPv4 地址。
\d{1,3}
匹配 1 到 3 位数字。\.
匹配 IP 地址中的点.
。
import re
pattern = r'^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$'
ips = ["192.168.1.1", "256.256.256,256", "127.0.0.1"]
for ip in ips:
if re.match(pattern, ip):
print(f"Valid: {ip}")
else:
print(f"Invalid: {ip}")
# 执行结果:
# Valid: 192.168.1.1
# Invalid: 256.256.256.256
# Valid: 127.0.0.1
6. 匹配 HTML 标签
正则表达式: r'<(\w+)[^>]*>(.*?)</\1>'
- 解释:匹配 HTML 标签及其内容。
<(\w+)
匹配标签名。[^>]*
匹配标签内的属性。>(.*?)
匹配标签内容。</\1>
匹配对应的闭合标签。
import re
pattern = r'<(\w+)[^>]*>(.*?)</\1>'
html = "<div class='test'>Hello World</div>"
match = re.search(pattern, html)
if match:
print(f"Tag: {match.group(1)}, Content: {match.group(2)}")
# 执行结果:
# Tag: div, Content: Hello World
7. 匹配中文字符
正则表达式: r'[\u4e00-\u9fff]+'
- 解释:匹配中文字符。
[\u4e00-\u9fff]
是中文字符的 Unicode 范围。
import re
pattern = r'[\u4e00-\u9fff]+'
text = "Hello 世界"
matches = re.findall(pattern, text)
print(matches) # 执行结果: ['世界']
8. 匹配密码强度
正则表达式: r'^(?=.*[A-Z])(?=.*[a-z])(?=.*\d)(?=.*[\W_]).{8,}$'
- 解释:匹配强密码(至少 8 位,包含大小写字母、数字和特殊字符)。
(?=.*[A-Z])
确保至少有一个大写字母。(?=.*[a-z])
确保至少有一个小写字母。(?=.*\d)
确保至少有一个数字。(?=.*[\W_])
确保至少有一个特殊字符。.{8,}
确保密码长度至少为 8。
import re
pattern = r'^(?=.*[A-Z])(?=.*[a-z])(?=.*\d)(?=.*[\W_]).{8,}$'
passwords = ["Password123!", "weakpass", "StrongPass1"]
for pwd in passwords:
if re.match(pattern, pwd):
print(f"Strong: {pwd}")
else:
print(f"Weak: {pwd}")
# 执行结果:
# Strong: Password123!
# Weak: weakpass
# Strong: StrongPass1
9. 匹配十六进制颜色值
正则表达式: r'^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$'
- 解释:匹配十六进制颜色值(如
#FFFFFF
或#FFF
)。 #
匹配颜色值开头的#
。[A-Fa-f0-9]{6}
匹配 6 位十六进制值。[A-Fa-f0-9]{3}
匹配 3 位十六进制值。
import re
pattern = r'^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$'
colors = ["#FFFFFF", "#FFF", "#123456", "#GHIJKL"]
for color in colors:
if re.match(pattern, color):
print(f"Valid: {color}")
else:
print(f"Invalid: {color}")
# 执行结果:
# Valid: #FFFFFF
# Valid: #FFF
# Valid: #123456
# Invalid: #GHIJKL
10. 匹配文件名和扩展名
正则表达式: r'^(\w+)\.(\w+)$'
- 解释:匹配文件名和扩展名。
(\w+)
匹配文件名。\.
匹配点.
。(\w+)
匹配扩展名。
import re
pattern = r'^(\w+)\.(\w+)$'
filename = "example.txt"
match = re.match(pattern, filename)
if match:
print(f"Filename: {match.group(1)}, Extension: {match.group(2)}")
# 执行结果:
# Filename: example, Extension: txt
11. 匹配整数
正则表达式: r'^-?\d+$'
- 解释:匹配正负整数。
-?
匹配可选的负号。\d+
匹配一个或多个数字。
import re
pattern = r'^-?\d+$'
numbers = ["123", "-456", "12.34"]
for num in numbers:
if re.match(pattern, num):
print(f"Valid: {num}")
else:
print(f"Invalid: {num}")
# 执行结果:
# Valid: 123
# Valid: -456
# Invalid: 12.34
12. 匹配浮点数
正则表达式: r'^-?\d+\.\d+$'
- 解释:匹配正负浮点数。
-?
匹配可选的负号。\d+
匹配整数部分。\.
匹配小数点。\d+
匹配小数部分。
import re
pattern = r'^-?\d+\.\d+$'
numbers = ["123.45", "-67.89", "123"]
for num in numbers:
if re.match(pattern, num):
print(f"Valid: {num}")
else:
print(f"Invalid: {num}")
# 执行结果:
# Valid: 123.45
# Valid: -67.89
# Invalid: 123
13. 匹配时间(HH:MM:SS)
正则表达式: r'^(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d$'
- 解释:匹配
HH:MM:SS
格式的时间。
import re
pattern = r'^(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d$'
times = ["12:34:56", "25:61:00", "09:00:00"]
for time in times:
if re.match(pattern, time):
print(f"Valid: {time}")
else:
print(f"Invalid: {time}")
# 执行结果:
# Valid: 12:34:56
# Invalid: 25:61:00
# Valid: 09:00:00
14. 匹配信用卡号
正则表达式: r'^\d{4}-\d{4}-\d{4}-\d{4}$'
- 解释:匹配常见的信用卡号格式(如
1234-5678-9012-3456
)。 \d{4}
匹配 4 位数字。-
匹配分隔符。
import re
pattern = r'^\d{4}-\d{4}-\d{4}-\d{4}$'
cards = ["1234-5678-9012-3456", "1234-5678-9012", "1234567890123456"]
for card in cards:
if re.match(pattern, card):
print(f"Valid: {card}")
else:
print(f"Invalid: {card}")
# 执行结果:
# Valid: 1234-5678-9012-3456
# Invalid: 1234-5678-9012
# Invalid: 1234567890123456
15. 匹配用户名
正则表达式: r'^[a-zA-Z0-9_]{4,16}$'
- 解释:匹配 4 到 16 位的用户名(字母、数字、下划线)。
[a-zA-Z0-9_]
匹配字母、数字和下划线。{4,16}
匹配长度为 4 到 16。
import re
pattern = r'^[a-zA-Z0-9_]{4,16}$'
usernames = ["user_123", "admin", "too_long_username_123"]
for username in usernames:
if re.match(pattern, username):
print(f"Valid: {username}")
else:
print(f"Invalid: {username}")
# 执行结果:
# Valid: user_123
# Valid: admin
# Invalid: too_long_username_123
以上是 15 个经典的正则表达式应用实例,涵盖了常见的文本匹配场景。通过这些例子,可以更好地理解和掌握正则表达式的使用。