Python正则表达式 r'(.*) are (.*?) .*' 贪婪与非贪婪模式解析
本文深入解析Python中正则表达式 r'(.*) are (.*?) .*' 的匹配机制。通过对比贪婪模式 (.*) 与非贪婪模式 (.*?) 的行为,结合多个代码示例,详细阐述分组捕获、无分组匹配及多are分隔符下的匹配结果差异,帮助开发者准确掌握正则表达式的核心逻辑。
正则表达式 r'(.*) are (.*?) .*' 基础解析
在Python3正则表达式的学习过程中,常会遇到一个经典示例。
#!/usr/bin/python3
import re
line = "Cats are smarter than dogs"
# .* 表示任意匹配除换行符(\n、\r)之外的任何单个或多个字符
# (.*?) 表示"非贪婪"模式,只保存第一个匹配到的子串
matchObj = re.match( r'(.*) are (.*?) .*', line, re.M|re.I)
if matchObj:
print ("matchObj.group() : ", matchObj.group())
print ("matchObj.group(1) : ", matchObj.group(1))
print ("matchObj.group(2) : ", matchObj.group(2))
else:
print ("No match!!")
该示例的运行结果如下。
matchObj.group() : Cats are smarter than dogs matchObj.group(1) : Cats matchObj.group(2) : smarter
该例子的核心正则表达式为 r'(.*) are (.*?) .*'。以下结合查阅的资料与实验结果,阐述个人理解。
- 前缀 r 表示原始字符串,即忽略转义字符,使编译器不处理反斜杠。但在本例中字符串不含反斜杠,因此 r 前缀可选。
- (.*) 是第一个匹配分组,.* 代表匹配除换行符(\n、\r)之外的所有字符。
- (.*?) 是第二个匹配分组,.*? 后的问号表示非贪婪模式,即仅匹配符合条件的最少字符。
- 末尾的 .* 未被括号包围,因此不构成分组,其匹配效果与第一个 .* 类似,但不计入匹配结果。
综上所述,该正则表达式以 are 为分隔点将字符串分为几部分:(.*?) 因贪婪模式返回所有满足条件的内容,而 (.*?) 因非贪婪模式仅返回第一个满足要求的内容或为空。
贪婪与非贪婪模式对比示例
若对匹配成功机制尚不理解,可参考以下示例。
#!/usr/bin/python3
import re
#line = "Cats are smarter than dogs"
line = "a a Cats are Cats are smarter than dogs"
# .* 表示任意匹配除换行符(\n、\r)之外的任何单个或多个字符
# (.*?) 表示"非贪婪"模式,只保存第一个匹配到的子串
matchObj = re.match( r'(.*) are (.*) .*', line, re.M|re.I)
if matchObj:
print ("matchObj.group() : ", matchObj.group())
print ("matchObj.group(1) : ", matchObj.group(1))
print ("matchObj.group(2) : ", matchObj.group(2))
else:
print ("No match!!")
输出结果如下。
matchObj.group() : a a Cats are Cats are smarter than dogs matchObj.group(1) : a a Cats are Cats matchObj.group(2) : smarter than
此例主要对第一个示例中的 line 字符串进行观察,并展示输出结果。
group(1) 对应第一个括号的条件,可理解为最后满足 are 分段前的所有内容。若将第一个括号改为 (.*?),则匹配第一个 are 前面的内容,经验证确实如此,此处省略代码供读者自行验证。
多分组与无分组匹配的深入分析
以下示例旨在进一步解释第二个括号内容及无括号的 .* 的作用。
#!/usr/bin/python3
import re
#line = "Cats are smarter than dogs"
line = "a a Cats are Cats are smarter than dogs"
# .* 表示任意匹配除换行符(\n、\r)之外的任何单个或多个字符
# (.*?) 表示"非贪婪"模式,只保存第一个匹配到的子串
matchObj = re.match( r'(.*?) are (.*) .* .*', line, re.M|re.I)
if matchObj:
print ("matchObj.group() : ", matchObj.group())
print ("matchObj.group(1) : ", matchObj.group(1))
print ("matchObj.group(2) : ", matchObj.group(2))
else:
print ("No match!!")
matchObj.group() : a a Cats are Cats are smarter than dogs matchObj.group(1) : a a Cats matchObj.group(2) : Cats are smarter
group(2) 对应第二个括号的条件:由于第一个括号内容添加了 ?,其索引内容为第一个 are 前面的部分;第二个括号则从当前 are 之后开始索引。此处未加 ?,因此输出为 .* 条件后的所有内容。
.* 因无 () 无法通过 group 访问,但会实际占用位置。上述示例最后使用两个 .*,因此最后占用两个单词,剩余部分即为 group(2) 的输出内容。
多are分隔符下的匹配验证
读者可自行尝试在语句中增加多个 are,并观察修改 ? 或括号后的效果。
#!/usr/bin/python3
import re
#line = "Cats are smarter than dogs"
line = "a a Cats are CatsB are smarter are than are dogs are dogs b c d e"
# .* 表示任意匹配除换行符(\n、\r)之外的任何单个或多个字符
# (.*?) 表示"非贪婪"模式,只保存第一个匹配到的子串
matchObj = re.match( r'(.*?) are (.*?) (.*?) (.*) .*', line, re.M|re.I)
if matchObj:
print ("matchObj.group() : ", matchObj.group())
print ("matchObj.group(1) : ", matchObj.group(1))
print ("matchObj.group(2) : ", matchObj.group(2))
print ("matchObj.group(3) : ", matchObj.group(3))
print ("matchObj.group(4) : ", matchObj.group(4))
else:
print ("No match!!")
matchObj.group() : a a Cats are CatsB are smarter are than are dogs are dogs b c d e matchObj.group(1) : a a Cats matchObj.group(2) : CatsB matchObj.group(3) : are matchObj.group(4) : smarter are than are dogs are dogs b c d
总结。
至此,关于Python正则表达式 r'(.*) are (.*?) .*' 的深入理解介绍完毕。更多相关内容请搜索本站以前的文章或继续浏览下面的相关文章,希望大家以后多多支持本站!
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









