import re # 不编译模式(重复编译) for _ in range(1000): result = re.match(r'\d+', '123') # 编译模式(仅编译一次) pattern = re.compile(r'\d+') for _ in range(1000): result = pattern.match('123')
针对多种情况测试正则表达式,确保其正确性。
import re # 示例:匹配电子邮件地址 pattern = re.compile(r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b') # 测试用例 test_cases = [ "user@example.com", # 有效的电子邮件 "user@company.co.uk", # 带国家代码的有效电子邮件 "name123@sub.domain.org", # 带子域名的有效电子邮件 "invalid_email@no_tld", # 无效的电子邮件(无顶级域名) "@missing_username.com", # 无效的电子邮件(无用户名) "user@invalid_domain", # 无效的电子邮件(域名无效) "name@server.c", # 无效的电子邮件(顶级域名过短) "name@server.with_space.com", # 无效的电子邮件(域名含空格) "user@@double_at.com", # 无效的电子邮件(含两个@) "user@excessive_length_domain." + "a" * 255# 无效的电子邮件(域名过长) ] # 用每个测试用例测试模式 for email in test_cases: match = pattern.match(email) print(f"{email}:{'有效'if match else'无效'}")
2.字符类
利用字符类(如 [a-z])匹配指定范围内的任意字符。
使用否定(字符类中的 ^)匹配不在指定范围内的字符(如 [^0-9] 匹配非数字)。
3.量词
需匹配最小内容时,优先使用非贪婪量词(*?、+?)。
使用贪婪量词(*、+)时需谨慎,避免意外的长匹配。
4.锚点和边界
使用 ^ 和 $ 分别将模式锚定到行的开头和结尾。
利用单词边界(\b)匹配完整单词。
5.选择和分组
使用选择(|)匹配多个模式(如 cat|dog)。
需对模式的特定部分(而非整个模式)应用量词(*、+、{})或选择(|)时,分组非常有用。
6.字符转义
熟悉常见的字符转义(\d、\w、\s),分别用于匹配数字、单词字符和空白字符。
若需匹配特殊字符(如 .),需转义(如 \.)。
7.环视
使用正向前瞻((?=...))匹配后面跟有特定模式的内容。
利用负向前瞻((?!...))匹配后面不跟特定模式的内容。
8.替换
使用捕获组在替换中提取并引用匹配字符串的部分内容。
import re # 示例:替换日期格式 pattern = re.compile(r'(\d{1,2})/(\d{1,2})/(\d{4})') # 原始字符串 text = "Meeting on 12/25/2022. Deadline is 3/8/2023." # 使用捕获组进行替换 result = pattern.sub(r'\3-\1-\2', text) # 打印结果 print(f"原始:{text}") print(f"修改后:{result}")
尝试使用反向引用(\1、\2)在替换中引用捕获组。
9.常见模式
使用 \d+ 匹配一个或多个数字。
使用 ? 匹配可选字符(如 colou?r 匹配 color 或 colour)。
使用 \s+ 匹配空白字符。
10.不区分大小写
使用 re.IGNORECASE 标志启用不区分大小写的匹配。
11.注释
使用 (?#comment) 在正则表达式中添加注释,提高可读性。
12.验证
使用健壮的正则表达式模式验证电子邮件地址。
import re defvalidate_email(email): # 电子邮件验证的正则表达式模式 pattern = re.compile(r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$') return bool(pattern.match(email)) # 测试用例 emails = [ "user@example.com", # 有效的电子邮件 "user.name@company.co.uk", # 带国家代码的有效电子邮件 "invalid_email@no_tld", # 无效的电子邮件(无顶级域名) "@missing_username.com", # 无效的电子邮件(无用户名) "user@invalid_domain", # 无效的电子邮件(域名无效) "user@@double_at.com", # 无效的电子邮件(含两个@) "user@excessive_length_domain." + "a" * 255# 无效的电子邮件(域名过长) ] # 验证每个电子邮件并打印结果 for email in emails: result = validate_email(email) print(f"{email}:{'有效'if result else'无效'}")
^[a-zA-Z0-9._%+-]+:匹配用户名部分中一个或多个允许的字符。
@:匹配 @ 符号。
[a-zA-Z0-9.-]+:匹配域名部分中一个或多个允许的字符。
\.:匹配顶级域名前的点(.)。
[a-zA-Z]{2,}$:匹配两个或多个字母的顶级域名。
为电话号码创建正则表达式模式。
import re defvalidate_phone_number(phone_number): # 带或不带连字符的美国电话号码的正则表达式模式 pattern = re.compile(r'^\+?1?\s*[-.]?\s*\(?\d{3}\)?[-.]?\s*\d{3}[-.]?\s*\d{4}$') return bool(pattern.match(phone_number)) # 测试用例 phone_numbers = [ "+1 123-456-7890", # 带国家代码的有效电话号码 "123.456.7890", # 带点的有效电话号码 "(123) 456-7890", # 带括号的有效电话号码 "1234567890", # 无连字符的有效电话号码 "987-654-3210", # 无国家代码的有效电话号码 "invalid_phone_number"# 无效的电话号码 ] # 验证每个电话号码并打印结果 for phone_number in phone_numbers: result = validate_phone_number(phone_number) print(f"{phone_number}:{'有效'if result else'无效'}")
import re defmatch_date_format_3(date_string): pattern = re.compile(r'^(0[1-9]|[12][0-9]|3[01])\s+(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s+\d{4}$', re.IGNORECASE) if pattern.match(date_string): print(f"{date_string} 匹配模式。") else: print(f"{date_string} 不匹配模式。") # 测试用例 dates_pattern_3 = ["25 Dec 2022", "08 March 2023", "15/07/2021", "31 October 2023", "invalid_date"] for date_str in dates_pattern_3: match_date_format_3(date_str)
import re defextract_content_from_html(html): # 匹配 HTML 标签内内容的正则表达式模式 pattern = re.compile(r']*>([^]*>') # 在 HTML 中查找所有匹配项 matches = pattern.findall(html) # 打印提取的内容 for match in matches: print(f"提取的内容:{match.strip()}") # HTML 字符串 html_content = """
Title
This is a sample paragraph.
Some italicized text.
""" # 从 HTML 标签提取内容 extract_content_from_html(html_content)
import re defextract_urls(text): # 提取 URL 的正则表达式模式 pattern = re.compile(r'https?://\S+|www\.\S+') # 在文本中查找所有匹配项 matches = pattern.findall(text) # 打印提取的 URL for match in matches: print(f"提取的 URL:{match}") # 测试用例 text_with_urls = """ Check out this website: https://www.example.com. For more information, visit http://www.another-example.org. """ # 从文本中提取 URL extract_urls(text_with_urls)
https?:匹配 "http" 或 "https"。
://:匹配 "://"。
\S+:匹配一个或多个非空白字符(域名)。
|:或运算符。
www\.\S+:匹配 "www." 后跟一个或多个非空白字符。
模式2:扩展 URL 提取
import re defextract_urls_extended(text): # 提取带可选 www 和查询参数的 URL 的正则表达式模式 pattern = re.compile(r'https?://(?:www\.)?\S+(?:\?\S+)?') # 在文本中查找所有匹配项 matches = pattern.findall(text) # 打印提取的 URL for match in matches: print(f"提取的 URL:{match}") # 测试用例 text_with_urls_extended = """ Check out this website: https://www.example.com/path/page?query=123. For more information, visit http://another-example.org. """ # 从文本中提取 URL extract_urls_extended(text_with_urls_extended)
(?:www\.)?:可选 "www." 的非捕获组。
(?:\?\S+)?):可选查询参数(以 "?" 开头)的非捕获组。
32.匹配 HTML 实体
使用正则表达式匹配或替换 HTML 实体。
import re from html import unescape defreplace_html_entities(text): # 匹配 HTML 实体的正则表达式模式 pattern = re.compile(r'&[a-zA-Z]+;') # 在文本中查找所有匹配项 matches = pattern.findall(text) # 将每个 HTML 实体替换为其解码后的等效字符 for match in matches: decoded_entity = unescape(match) text = text.replace(match, decoded_entity) return text # 测试用例 html_text = "This is an example with HTML entities." # 替换文本中的 HTML 实体 result_text = replace_html_entities(html_text) # 打印结果 print("原始文本:", html_text) print("替换后:", result_text)
正则表达式模式 &[a-zA-Z]+; 用于匹配常见的 HTML 实体。然后使用 html 模块中的 unescape 函数将每个 HTML 实体替换为其解码后的等效字符。
33.匹配文件路径
设计正则表达式模式匹配文件路径。
模式1:Unix/Linux 文件路径
import re defmatch_unix_file_path(path): # 匹配 Unix/Linux 文件路径的正则表达式模式 pattern = re.compile(r'^\/(?:[^\/]+\/)*[^\/]+$') if pattern.match(path): print(f"{path} 是有效的 Unix/Linux 文件路径。") else: print(f"{path} 不是有效的 Unix/Linux 文件路径。") # 测试用例 unix_paths = [ "/home/user/documents/file.txt", "/var/www/html/index.html", "relative/path/to/file", "invalid\\path\\file.txt" ] for path in unix_paths: match_unix_file_path(path)
^:断言字符串的开头。
\/:匹配根目录("/")。
(?:[^\/]+\/)*:非捕获组,匹配零个或多个非斜杠字符后跟斜杠的序列。
[^\/]+$:匹配字符串末尾一个或多个非斜杠字符。
模式2:Windows 文件路径
import re defmatch_windows_file_path(path): # 匹配 Windows 文件路径的正则表达式模式 pattern = re.compile(r'^[a-zA-Z]:\\(?:[^\\]+\\)*[^\\]+$') if pattern.match(path): print(f"{path} 是有效的 Windows 文件路径。") else:
print(f"{path} 不是有效的 Windows 文件路径。") # 测试用例 windows_paths = [ "C:\\Users\\User\\Documents\\file.txt", "D:/Projects/project1/code.py", "\\absolute\\path\\file.txt", "/unix/style/path/file" ] for path in windows_paths: match_windows_file_path(path)
^:断言字符串的开头。
[a-zA-Z]:\\:匹配驱动器号(例如,"C:")后跟反斜杠。
(?:[^\\]+\\)*:非捕获组,匹配零个或多个非反斜杠字符后跟反斜杠的序列。
[^\\]+$:匹配字符串末尾一个或多个非反斜杠字符。
34.提取电子邮件地址
创建正则表达式模式从文本中提取电子邮件地址。
模式1:基本电子邮件地址提取
import re defextract_email_addresses(text): # 基本电子邮件地址提取的正则表达式模式 pattern = re.compile(r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b') # 在文本中查找所有匹配项 matches = pattern.findall(text) # 打印提取的电子邮件地址 for match in matches: print(f"提取的电子邮件:{match}") # 测试用例 text_with_emails = """ Contact us at support@example.com for assistance. Send your inquiries to info@company.org or sales@business.com. Invalid emails: user@invalid, @missing_username.com, email@in@valid.com """ # 从文本中提取电子邮件地址 extract_email_addresses(text_with_emails)
import re defextract_email_addresses_extended(text): # 扩展电子邮件地址提取的正则表达式模式 pattern = re.compile(r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}(?:\.[A-Z|a-z]{2,})?\b') # 在文本中查找所有匹配项 matches = pattern.findall(text) # 打印提取的电子邮件地址 for match in matches: print(f"提取的电子邮件:{match}") # 测试用例 text_with_emails_extended = """ Contact us at support@example.com for assistance. Send your inquiries to info@company.org or sales@business.co.uk. Invalid emails: user@invalid, @missing_username.com, email@in@valid.com """ # 从文本中提取电子邮件地址 extract_email_addresses_extended(text_with_emails_extended)
...(?:\.[A-Z|a-z]{2,})?\b
(?: ... )?:可选附加子域名的非捕获组。
\.:匹配附加子域名前的点。
[A-Z|a-z]{2,}:匹配至少2个字符的附加子域名。
35.匹配 IPv4 地址
设计正则表达式模式匹配 IPv4 地址。
模式1:基本 IPv4 地址匹配
import re defmatch_ipv4_addresses(text): # 基本 IPv4 地址匹配的正则表达式模式 pattern = re.compile(r'\b(?:\d{1,3}\.){3}\d{1,3}\b') # 在文本中查找所有匹配项 matches = pattern.findall(text) # 打印匹配的 IPv4 地址 for match in matches: print(f"匹配的 IPv4 地址:{match}") # 测试用例 text_with_ipv4 = """ Server 1: 192.168.1.1 Server 2: 10.0.0.255 Invalid IP: 256.256.256.256 """ # 在文本中匹配 IPv4 地址 match_ipv4_addresses(text_with_ipv4)
\b(?:\d{1,3}\.){3}\d{1,3}\b
\b:单词边界,确保匹配整个 IPv4 地址。
(?:\d{1,3}\.){3}:非捕获组,匹配三次 "1-3 位数字后跟点"。
\d{1,3}:匹配最后一个八位字节(1-3 位数字)。
模式2:扩展 IPv4 地址匹配
import re defmatch_ipv4_addresses_extended(text): # 扩展 IPv4 地址匹配的正则表达式模式 pattern = re.compile(r'\b(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)' r'(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}\b') # 在文本中查找所有匹配项 matches = pattern.findall(text) # 打印匹配的 IPv4 地址 for match in matches: print(f"匹配的 IPv4 地址:{match}") # 测试用例 text_with_ipv4_extended = """ Server 1: 192.168.1.1 Server 2: 10.0.0.255 Invalid IP: 256.256.256.256 """ # 在文本中匹配 IPv4 地址 match_ipv4_addresses_extended(text_with_ipv4_extended)
\b(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)
(?: ... ){3}:非捕获组,匹配三次以下模式。
25[0-5]:匹配 250 到 255 之间的数字。
2[0-4][0-9]:匹配 200 到 249 之间的数字。
[01]?[0-9][0-9]?:匹配 0 到 199 之间的数字。
36.转义符上的量词
将量词直接应用于转义符(例如,\d{3} 匹配三位数字)。
37.匹配信用卡号
创建正则表达式模式匹配或验证信用卡号。
模式1:基本信用卡号验证
import re defvalidate_credit_card_number_basic(card_number): # 基本信用卡号验证的正则表达式模式 pattern = re.compile(r'^\d{13,19}$') if pattern.match(card_number): print(f"{card_number} 可能是有效的信用卡号。") else: print(f"{card_number} 不是有效的信用卡号。") # 测试用例 credit_cards_basic = [ "1234567890123", "4567-8901-2345-6789", "1234 5678 9012 3456", "invalid_card", ] for card in credit_cards_basic: validate_credit_card_number_basic(card)
^\d{13,19}$:匹配长度在13到19个字符之间的数字字符串。
模式2:带卢恩算法的信用卡号验证
import re defvalidate_credit_card_number_luhn(card_number): # 带卢恩算法的信用卡号验证的正则表达式模式 pattern = re.compile(r'^\d{13,19}$') ifnot pattern.match(card_number): print(f"{card_number} 不是有效的信用卡号。") return # 移除非数字字符 digits = [int(digit) for digit in card_number if digit.isdigit()] # 应用卢恩算法 total = sum(digits[::-2] + [sum(divmod(d * 2, 10)) for d in digits[-2::-2]]) if total % 10 == 0: print(f"{card_number} 是有效的信用卡号。") else: print(f"{card_number} 不是有效的信用卡号。") # 测试用例 credit_cards_luhn = [ "1234567890123", "4567-8901-2345-6789", "1234 5678 9012 3456", "invalid_card", ] for card in credit_cards_luhn: validate_credit_card_number_luhn(card)
^\d{13,19}$:与基本模式相同,用于初始数字验证。
卢恩算法用于检查信用卡号的有效性。
38.匹配特定单词
使用 \b 匹配较大文本中的特定单词。
39.转义字符
使用 \ 转义特殊字符,如 ^、$、(、)、[、]、{、}、.、*、+、?、|、\。
在非特殊字符前使用 \ 以字面匹配它。
40.Unicode 和单词边界
使用 \b 作为单词边界,\B 作为非单词边界。
对于 Unicode 单词边界,结合 re.UNICODE 标志使用 \b。
41.匹配或排除字符
使用 . 匹配除换行符外的任何字符。
使用 [^...] 匹配不在指定集合中的任何字符。
42.量词组合
组合量词以提高灵活性(例如,a{2,4} 匹配 'aa'、'aaa' 或 'aaaa')。
使用 {0,} 或 * 表示零次或多次出现。
43.分组和选择
使用括号进行分组,并对序列应用量词。
import re # 包含电话号码的示例文本 text = """ Phone Numbers: - (555) 123-4567 - (123) 456-7890 - (987) 654-3210 """ # 带分组和量词的正则表达式模式,用于匹配电话号码 pattern = re.compile(r'\(\d{3}\) \d{3}-\d{4}') # 在文本中查找所有匹配项 matches = pattern.findall(text) # 打印匹配的电话号码 for match in matches: print("匹配的电话号码:", match)
\(:匹配左括号。
\d{3}:匹配恰好三位数字。
\):匹配右括号。
:匹配空格。
\d{3}:匹配恰好三位数字。
-:匹配连字符。
\d{4}:匹配恰好四位数字。
利用 (?:...) 作为非捕获组。
利用选择匹配多个可能的模式(例如,cat|dog|bird)。
44.替换中的捕获组
在替换模式中使用 \1、\2 等利用捕获组。
对命名捕获组使用 \g。
45.环视
使用正向后顾((?<=...))匹配前面有特定模式的内容。
应用负向后顾((?)匹配前面没有特定模式的内容。
利用正向前瞻((?=...))匹配后面有特定模式的内容。
利用负向前瞻((?!...))匹配后面没有特定模式的内容。
46.命名捕获组
使用命名捕获组提高代码可读性。
使用 match.group('name') 访问命名捕获组。
47.详细模式
启用详细模式(re.VERBOSE 或 re.X),支持多行模式和注释。
将复杂模式拆分为多行,提高可读性。
import re # 包含电子邮件地址的示例文本 text = """ Email Addresses: - user@example.com - john.doe@company.org - contact@my-website.co.uk """ # 带换行符的正则表达式模式,提高可读性 pattern = re.compile( r'\b'# 单词边界 r'[a-zA-Z0-9._%+-]+@'# 用户名部分 r'[a-zA-Z0-9.-]+\.'# 域名部分(第一级) r'[A-Z|a-z]{2,}'# 域名部分(顶级) r'\b'# 单词边界 ) # 在文本中查找所有匹配项 matches = pattern.findall(text) # 打印匹配的电子邮件地址 for match in matches: print("匹配的电子邮件地址:", match)
import re defextract_xml_content(xml_text, tag_name): # 匹配并提取 XML 标签之间内容的正则表达式模式 pattern = re.compile(rf'<{tag_name}[^>]*>(.*?){tag_name}>', re.DOTALL) # 在文本中查找所有匹配项 matches = pattern.findall(xml_text) # 打印提取的内容 print(f"<{tag_name}> 标签之间的内容:") for match in matches: print(match.strip()) # 测试用例 sample_xml = """ Introduction to XML John Doe This is a sample book about XML. """ extract_xml_content(sample_xml, 'title') extract_xml_content(sample_xml, 'content')
该模式用于捕获指定 XML 标签之间的内容。
rf']*>(.*?)':通过 f 字符串动态插入标签名,匹配开始标签 与对应结束标签 之间的内容。
re.DOTALL 标志使正则表达式中的 . 能匹配包括换行符在内的所有字符。
需注意,此示例适用于无嵌套标签的简单场景。对于复杂 XML 解析,建议使用 ElementTree 或 lxml 等专用 XML 解析库,它们能更精准地处理 XML 结构。
若 XML 的开始标签包含属性,可调整模式以适配,例如用 (\w+)\s*=\s*["']([^"']*)["'] 捕获属性名和属性值。
若 XML 包含命名空间前缀,可使用适配模式(如 (\w+:)?(\w+))同时捕获命名空间前缀和本地名称。
61.匹配句子
创建模式匹配文本中的完整句子。
import re defextract_sentences(text): # 匹配英文完整句子的正则表达式模式
pattern = re.compile(r'(?) # 按模式将文本拆分为句子 sentences = re.split(pattern, text) # 打印提取的句子 print("提取的句子:") for sentence in sentences: print(sentence.strip()) # 测试用例 sample_text = """ This is the first sentence. It contains multiple words. The second sentence has more words. It also ends with a period. A third sentence exists as well, with a question mark at the end? """ extract_sentences(sample_text)
import re defextract_html_comments(html_text): # 匹配并提取 HTML 注释内内容的正则表达式模式 pattern = re.compile(r'', re.DOTALL) # 在文本中查找所有匹配项 matches = pattern.findall(html_text) # 打印提取的内容 print("HTML 注释内的内容:") for match in matches: print(match.strip()) # 测试用例 sample_html = """ HTML Comments Example
This is a paragraph.
More content
""" extract_html_comments(sample_html)
pattern 正则表达式使用非贪婪匹配 (.*?) 捕获 之间的内容。
re.DOTALL:标志使正则表达式中的点(.)匹配包括换行符在内的所有字符。
需要注意的是,虽然此示例在简单场景下可行,但使用正则表达式解析 HTML 注释可能无法覆盖所有边缘情况。对于更可靠的 HTML 解析,建议使用 Python 中的 BeautifulSoup 或 lxml 等专用 HTML 解析库,这些库专为处理 HTML 结构的复杂性而设计,能提供更可靠的 HTML 文档解析方案。
63.匹配浮点数
创建正则表达式模式匹配浮点数。
import re defextract_float_numbers(text): # 匹配浮点数的正则表达式模式 pattern = re.compile(r'-?\b(?:\d+\.\d*|\.\d+|\d+)(?:[eE][-+]?\d+)?\b') # 在文本中查找所有匹配项 matches = pattern.findall(text) # 打印提取的浮点数 print(
"提取的浮点数:") for match in matches: print(match) # 测试用例 sample_text = """ 文本中的数字:3.14、-0.5、123.456、.789、1.2e3、-4.56E-7 非数字:abc、1.2.3、1e、1E2.5 """ extract_float_numbers(sample_text)
pattern 正则表达式捕获多种格式的浮点数,各部分含义如下:
-?:可选的负号,用于匹配负数。
\b:单词边界,确保匹配完整的数字。
(?:\d+\.\d*|\.\d+|\d+):用于匹配三种情况的分组:
\d+\.\d*:带整数部分且小数部分可选的十进制数。
\.\d+:以小数点开头的十进制数。
\d+:无小数点的整数部分。
(?:[eE][-+]?\d+)?:可选的指数部分,形式为 e 或 E 后跟可选符号及数字。
64.验证 MAC 地址
设计正则表达式模式验证 MAC 地址。
import re defvalidate_mac_address(mac_address): # 验证 MAC 地址的正则表达式模式 pattern = re.compile(r'^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$') # 检查 MAC 地址是否匹配模式 return bool(pattern.match(mac_address)) # 测试用例 mac_addresses = [ "00:1a:2b:3c:4d:5e", "01-23-45-67-89-ab", "a1:b2:c3:d4:e5:f6", "invalid_mac", ] for mac_address in mac_addresses: if validate_mac_address(mac_address): print(f"{mac_address} 是有效的 MAC 地址。") else: print(f"{mac_address} 不是有效的 MAC 地址。")
pattern 正则表达式验证格式为 XX:XX:XX:XX:XX:XX 或 XX-XX-XX-XX-XX-XX 的 MAC 地址,其中 X 为十六进制数字(0-9、A-F、a-f)。
^:匹配字符串的开头。
([0-9A-Fa-f]{2}[:-]){5}:匹配五组两位十六进制数字后跟冒号或连字符的组合。
([0-9A-Fa-f]{2}):匹配最后一组两位十六进制数字。
$:匹配字符串的结尾。
此模式确保 MAC 地址由六组两位十六进制数字组成,各组之间用冒号或连字符分隔。可根据特定的 MAC 地址要求或格式变体进行调整。