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}$'

上一篇 下一篇

猜你喜欢

热点阅读