python中re.findall的一个捕获分组问题
2020-01-17 本文已影响0人
有时右逝
问题描叙
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2020/1/12 上午8:39
# @Author : hiwower
# @Site :
# @File : test-mac.py
# @Software: PyCharm
import re
p = '^([A-F0-9]{2}:){5}[A-F0-9]{2}$'
string = '81:0B:7C:18:32:A0'
print(re.findall(p,string))
print(re.match(p,string).group())
上面的代码期望执行结果是匹配mac地址 81:0B:7C:18:32:A0
实际输出
['32:']
81:0B:7C:18:32:A0
因此只有re.match正确得到预期。而findall没有。
原因
直接查看findall的定义
def findall(pattern, string, flags=0):
"""Return a list of all non-overlapping matches in the string.
If one or more capturing groups are present in the pattern, return
a list of groups; this will be a list of tuples if the pattern
has more than one group.
Empty matches are included in the result."""
return _compile(pattern, flags).findall(string)
这里的理解我翻译以下:
返回结果是 一个列表;
列表中每个元素的值的类型,取决于你的正则表达式的写法
1、当你的正则表达式中有(带捕获的)分组(简单可理解为有括号)
值,是分组匹配的结果
2、当你的正则表达式中没有捕获的组(不分组,或非捕获分组)
值,是你的正则表达式所匹配到的单个完整的字符串
分析
以上面的例子来分析
p = '^([A-F0-9]{2}:){5}[A-F0-9]{2}$'
存在带捕获的分组。
因此得到的该分组的值。因此结果是 ['32:']
再举个其他的例子
print(re.findall('(ab)+123','ababab123 abc123 abb123 aa1234 ab1234'))
这里期望是匹配出 ['ababab123', 'ab123']
但是实际得到的只有 ['ab', 'ab']
正确的写法
print(re.findall('(?:ab)+123','ababab123 abc123 abb123 aa1234 ab1234'))
解决
一种方法是去掉 捕获分组。就是去掉()
p = '^[A-F0-9]{2}:[A-F0-9]{2}:[A-F0-9]{2}:[A-F0-9]{2}:[A-F0-9]{2}:[A-F0-9]{2}$'
一种方法是将捕获的分组修改成 非捕获的分组。只需要添加?:
即可。
p = '^(?:[A-F0-9]{2}:){5}[A-F0-9]{2}$'