Python 正则表达式进阶用法:量词与范围
在掌握了正则表达式的基础知识后,学习一些进阶用法能更有效地处理复杂的文本匹配任务。量词和范围是正则表达式中用来控制匹配次数和限定字符范围的重要部分。在 Python 中,re
模块提供了强大的正则表达式功能,配合使用量词和范围,我们可以轻松实现各种文本操作,如匹配特定长度的数字、查找某些字符范围内的单词等。
本文将详细介绍 Python 正则表达式中的量词和范围,并结合示例讲解这些进阶用法的实际应用。
1. 正则表达式的量词
量词(Quantifiers)用于定义正则表达式中某一部分的匹配次数。量词有很多种,例如匹配某个字符零次或多次、一到多次、特定次数等。了解这些量词的用法可以大大提升正则表达式的灵活性。
1.1 常用量词介绍
以下是常用的正则表达式量词及其含义:
*
:匹配前面的字符零次或多次,相当于"任意多次"。+
:匹配前面的字符一次或多次,相当于"至少一次"。?
:匹配前面的字符零次或一次,相当于"可有可无"。{n}
:匹配前面的字符n
次。{n,}
:匹配前面的字符至少n
次。{n, m}
:匹配前面的字符n
到m
次。
1.2 示例代码
python
import re
# 使用 * 量词匹配任意多次
pattern_star = r"ab*"
print(re.findall(pattern_star, "abbb a abbbb aaaa")) # 匹配 'a' 后跟零个或多个 'b'
# 使用 + 量词匹配一次或多次
pattern_plus = r"ab+"
print(re.findall(pattern_plus, "abbb a abbbb aaaa")) # 匹配 'a' 后跟一个或多个 'b'
# 使用 ? 量词匹配零次或一次
pattern_question = r"ab?"
print(re.findall(pattern_question, "abbb a abbbb aaaa")) # 匹配 'a' 后跟零个或一个 'b'
# 使用 {n} 量词匹配指定次数
pattern_exact = r"ab{3}"
print(re.findall(pattern_exact, "abbb a abbbb aaaa")) # 匹配 'a' 后跟正好三个 'b'
# 使用 {n,} 量词匹配至少 n 次
pattern_min = r"ab{2,}"
print(re.findall(pattern_min, "abbb a abbbb aaaa")) # 匹配 'a' 后跟至少两个 'b'
# 使用 {n, m} 量词匹配 n 到 m 次
pattern_range = r"ab{2,4}"
print(re.findall(pattern_range, "abbb a abbbb aaaa")) # 匹配 'a' 后跟 2 到 4 个 'b'
1.3 结果分析
输出:
['abbb', 'a', 'abbbb', 'a'] # * 匹配零次或多次
['abbb', 'abbbb'] # + 匹配一次或多次
['ab', 'a', 'ab', 'a'] # ? 匹配零次或一次
['abbb', 'abbb'] # {3} 匹配恰好 3 次
['abbb', 'abbbb'] # {2,} 至少 2 次
['abbb', 'abbb'] # {2,4} 匹配 2 到 4 次
上述示例展示了各种量词的匹配效果,通过调整量词,可以灵活控制字符的出现次数。
2. 正则表达式的范围
范围用于限定正则表达式匹配的字符集。通过使用方括号 []
,我们可以指定允许匹配的字符。范围与量词的结合可以创建更加灵活的匹配模式。
2.1 常用范围写法
范围通常用于在字符类中限定字符集,例如:
[abc]
:匹配a
、b
或c
。[a-z]
:匹配小写字母a
到z
。[A-Z]
:匹配大写字母A
到Z
。[0-9]
:匹配数字0
到9
。[^abc]
:匹配除了a
、b
、c
以外的任何字符。
2.2 范围的应用示例
python
import re
# 匹配小写字母 a 到 c
pattern_abc = r"[a-c]"
print(re.findall(pattern_abc, "abcdefg ABCDEFG")) # 输出 ['a', 'b', 'c']
# 匹配数字
pattern_digits = r"[0-9]+"
print(re.findall(pattern_digits, "My phone number is 12345")) # 输出 ['12345']
# 匹配大写字母
pattern_upper = r"[A-Z]"
print(re.findall(pattern_upper, "Hello World")) # 输出 ['H', 'W']
# 匹配非数字字符
pattern_non_digits = r"[^0-9]+"
print(re.findall(pattern_non_digits, "123abc456def789")) # 输出 ['abc', 'def']
在上述示例中,我们使用范围定义了具体的匹配字符。对于文本处理中常见的字母和数字提取,范围是非常方便的选择。
2.3 范围与量词结合的应用
范围和量词结合可以创建更加复杂的正则表达式模式。例如,匹配一个 5 位的数字可以通过 [0-9]{5}
来实现。
python
import re
# 匹配 5 位数字
pattern_zipcode = r"[0-9]{5}"
print(re.findall(pattern_zipcode, "My postal code is 12345")) # 输出 ['12345']
# 匹配 2 到 5 位的数字
pattern_digits_range = r"[0-9]{2,5}"
print(re.findall(pattern_digits_range, "Zip codes: 123, 4567, 89")) # 输出 ['123', '4567', '89']
# 匹配邮箱格式(以简单的形式展示)
pattern_email = r"[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}"
emails = "Contact us at info@example.com or support@test.co"
print(re.findall(pattern_email, emails)) # 输出 ['info@example.com', 'support@test.co']
3. 贪婪与非贪婪匹配
在 Python 正则表达式中,量词默认是"贪婪"的,也就是说它会尽可能多地匹配字符。为了实现更精确的匹配,有时需要将贪婪量词改为非贪婪匹配。
3.1 贪婪量词
贪婪量词会尽可能多地匹配字符。例如,对于字符串 "<p>Content</p>"
,使用 "<.*>"
会匹配整个字符串,而不仅是 <p>
标签中的内容。
3.2 非贪婪量词
在量词后面加上 ?
可以实现非贪婪匹配,即尽可能少地匹配字符。例如,"<.*?>"
只会匹配 <p>
标签中的内容,而不是整个字符串。
示例代码
python
import re
text = "<p>Content</p> <a>Link</a>"
# 贪婪匹配
greedy_pattern = r"<.*>"
print("贪婪匹配:", re.findall(greedy_pattern, text)) # 输出 ['<p>Content</p> <a>Link</a>']
# 非贪婪匹配
non_greedy_pattern = r"<.*?>"
print("非贪婪匹配:", re.findall(non_greedy_pattern, text)) # 输出 ['<p>', '</p>', '<a>', '</a>']
在上述代码中,贪婪匹配和非贪婪匹配的结果不同。贪婪匹配会匹配尽可能多的内容,而非贪婪匹配会在最小范围内完成匹配。
4. 实战应用:复杂文本解析
为了更好地理解量词和范围在实际中的应用,我们来实现一个复杂文本解析的示例。假设我们需要解析一段文本中的电子邮件地址和电话号码。
示例代码
python
import re
text = """
Contact: John Doe, Email: john.doe@example.com, Phone: (123) 456-7890.
Support: Jane Smith
, Email: jane_smith123@test.co.uk, Phone: 987-654-3210.
"""
# 邮箱匹配
email_pattern = r"[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}"
emails = re.findall(email_pattern, text)
print("邮箱地址:", emails)
# 电话号码匹配
phone_pattern = r"\(?\d{3}\)?[-\s]?\d{3}[-\s]?\d{4}"
phones = re.findall(phone_pattern, text)
print("电话号码:", phones)
输出结果
邮箱地址: ['john.doe@example.com', 'jane_smith123@test.co.uk']
电话号码: ['(123) 456-7890', '987-654-3210']
此示例中,我们使用了量词和范围成功提取了邮箱地址和电话号码。在邮箱匹配中使用了贪婪匹配 +
,在电话号码匹配中结合了量词 {}
和字符范围。
5. 总结
掌握 Python 正则表达式中的量词和范围,可以灵活处理文本中的多种匹配需求。从基本的字符匹配到复杂的文本解析,量词和范围为正则表达式提供了强大的扩展能力。通过量词控制字符出现的次数,使用范围指定匹配字符集合,我们可以轻松实现文本分析和数据提取等任务。