Bootstrap

Python3 【正则表达式】:经典示例参考手册

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.IGNORECASEre.I:忽略大小写。
  • re.MULTILINEre.M:多行模式,^$ 匹配每行的开头和结尾。
  • re.DOTALLre.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? 匹配 httphttps
  • :// 匹配 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 个经典的正则表达式应用实例,涵盖了常见的文本匹配场景。通过这些例子,可以更好地理解和掌握正则表达式的使用。

;