python笔记52-re正则匹配search(group groups groupdict)

前言

re.search扫描整个字符串并返回第一个成功的匹配。re.findall返回字符串中所有不重叠匹配项的列表,如果没有匹配到返回空list不会报错。
search匹配对象有3个方法:group() groups() groupdict() ,这3个方法使用上会有一些差异。
如果只需匹配一个,匹配到就结束就用search,匹配全部就用findall

re.search 源码解读

search扫描整个字符串并返回第一个成功的匹配,如果没匹配到返回None
函数参数说明:

  • pattern 匹配的正则表达式
  • string 要匹配的字符串。
  • flags 标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等
def search(pattern, string, flags=0):
    """Scan through string looking for a match to the pattern, returning
    a match object, or None if no match was found."""
    return _compile(pattern, flags).search(string)

跟前面findall一样有三种方式

import re


kk = re.compile(r'\d+')  # 匹配数字
res1 = kk.search('one1two2three3four4')
print(res1)
# <_sre.SRE_Match object; span=(3, 4), match='1'>

kk = re.compile(r'\d+')
res2 = re.search(kk,"one123two2")
print(res2)
# <_sre.SRE_Match object; span=(3, 6), match='123'>

# 也可以直接在search传2个参数
res3 = re.search(r'\d+', "one123two2")
print(res3)
print(res3.group(0))
# <_sre.SRE_Match object; span=(3, 6), match='123'>
# 123

不同的是匹配成功re.search方法返回一个匹配的对象,否则返回None。

我们可以使用group(num) 或 groups() 匹配对象函数来获取匹配表达式。

  • group(num=0) 匹配的整个表达式的字符串,group() 可以一次输入多个组号,在这种情况下它将返回一个包含那些组所对应值的元组。
  • groups() 返回一个包含所有小组字符串的元组,从 1 到 所含的小组号。
search 示例

先看第一个案例,找出下面文本中的blog地址

import re


# 取出 blog 地址
a = '作者-上海悠悠 QQ交流群:717225969 blog地址:https://www.cnblogs.com/yoyoketang/ 欢迎收藏'
res = re.search(r'blog地址:(.*?) 欢迎收藏', a)
print(res)  # 返回Match object
print(res.group(1))

# 打印内容
# <_sre.SRE_Match object; span=(24, 71), match='blog地址:https://www.cnblogs.com/yoyoketang/ 欢迎收藏'>
# https://www.cnblogs.com/yoyoketang/

如果匹配到返回一个Match object对象,用group(1)取出匹配的值。

如果没匹配到返回的是None,调用group(1)方法会抛异常

import re


# 取出 blog 地址
a = '作者-上海悠悠 QQ交流群:717225969 blog地址:https://www.cnblogs.com/yoyoketang/ 欢迎收藏'
res = re.search(r'blog地址X:(.*?) 欢迎收藏', a)
print(res)  # 返回Match object
print(res.group(1))

会抛出异常

Traceback (most recent call last):
  File "D:/soft/git/web_git/case/a.py", line 29, in <module>
    print(res.group(1))
None
AttributeError: 'NoneType' object has no attribute 'group'

于是可以加个判断再取值: result = res.group(1) if res else None

import re


# 取出 blog 地址
a = '作者-上海悠悠 QQ交流群:717225969 blog地址:https://www.cnblogs.com/yoyoketang/ 欢迎收藏'
res = re.search(r'blog地址:(.*?) 欢迎收藏', a)
print(res)  # 返回Match object
# 加个判断,如果没匹配到给None值
result = res.group(1) if res else None
print(result)
group()的使用

group(0) 是获取取得的字符串整体,group(1)是取出括号里面我们要匹配的内容
group(0)和group()效果相同,均为获取取得的字符串整体

import re


# 取出 blog 地址
a = '作者-上海悠悠 QQ交流群:717225969 blog地址:https://www.cnblogs.com/yoyoketang/ 欢迎收藏'
res = re.search(r'blog地址:(.*?) 欢迎收藏', a)
# print(res)  # 返回Match object
# 加个判断,如果没匹配到给None值
result1 = res.group(0) if res else None
print(result1)  # blog地址:https://www.cnblogs.com/yoyoketang/ 欢迎收藏
result2 = res.group(1) if res else None
print(result2)  # https://www.cnblogs.com/yoyoketang/

如果整个字符串中,有多个值需要匹配呢?我想同时取出QQ群号和blog地址

import re

# 取出 blog 地址
a = '作者-上海悠悠 QQ交流群:717225969 blog地址:https://www.cnblogs.com/yoyoketang/ 欢迎收藏'
res = re.search(r'QQ交流群:(\d+) blog地址:(.*?) 欢迎收藏', a)
# print(res)  # 返回Match object
# 加个判断,如果没匹配到给None值
result1 = res.group(0) if res else None
print(result1)  # QQ交流群:717225969 blog地址:https://www.cnblogs.com/yoyoketang/ 欢迎收藏
result2 = res.group(1) if res else None
print(result2)  # 717225969
result3 = res.group(2) if res else None
print(result3)  # https://www.cnblogs.com/yoyoketang/

于是很好理解了:

  • group() 跟group(0)一样是获取匹配的整个字符串
  • group(0) 是获取匹配的整个字符串
  • group(1) 取出匹配的第一个值
  • group(2) 取出匹配的第二个值
  • group(0, 1, 2) 同时取出上面对应的三个值,返回元祖

group()也可以同时取出三个值,使用group(0, 1, 2)

import re


# 取出 blog 地址
a = '作者-上海悠悠 QQ交流群:717225969 blog地址:https://www.cnblogs.com/yoyoketang/ 欢迎收藏'
res = re.search(r'QQ交流群:(\d+) blog地址:(.*?) 欢迎收藏', a)
# print(res)  # 返回Match object
# 同时取出三个值,返回的是元祖()
result = res.group(0, 1, 2) if res else None
print(result)          # ('QQ交流群:717225969 blog地址:https://www.cnblogs.com/yoyoketang/ 欢迎收藏', '717225969', 'https://www.cnblogs.com/yoyoketang/')
# 分别复制给3个结果
result1, result2, result3 = res.group(0, 1, 2) if res else None
print(result1)         # QQ交流群:717225969 blog地址:https://www.cnblogs.com/yoyoketang/ 欢迎收藏
print(result2)         # 717225969
print(result3)         # https://www.cnblogs.com/yoyoketang/ 
groups()的使用

匹配对象的groups()方法返回一个包含所有参与匹配的子组(不含组0)的匹配到的搜索文本子串的元组。
先看一个案例,就能理解上面这句话了

import re


# 取出 blog 地址
a = '作者-上海悠悠 QQ交流群:717225969 blog地址:https://www.cnblogs.com/yoyoketang/ 欢迎收藏'
res = re.search(r'QQ交流群:(\d+) blog地址:(.*?) 欢迎收藏', a)
# print(res)  # 返回Match object

# 返回一个包含所有参与匹配的子组(不含组0)
print(res.groups())  # 返回 ('717225969', 'https://www.cnblogs.com/yoyoketang/')

# 返回匹配的group(1), group(2) 其中不含group(0)
print(res.group(1, 2))  # 返回 ('717225969', 'https://www.cnblogs.com/yoyoketang/')

前面讲到group(0, 1, 2)可以获取到3个值,但是group(0)我们一般不常用,一般是获取后面两个要取的值。
这里的groups() 的功能就是取出所有的要匹配的值,不包含group(0)

groupdict() 的使用

groupdict返回一个包含所有匹配到的命名组的组名为键值和命名组匹配到的搜索文本子串为值作为元素的字典,且groudict仅能访问命名组数据。

先看一个示例

import re


# 取出 blog 地址
a = '作者-上海悠悠 QQ交流群:717225969 blog地址:https://www.cnblogs.com/yoyoketang/ 欢迎收藏'
res = re.search(r'QQ交流群:(\d+) blog地址:(.*?) 欢迎收藏', a)
# print(res)  # 返回Match object
print(res.groupdict()) # 返回 {}

上面的匹配返回有个空的dict,因为我们没用到变量命名匹配的内容,这种里面定义变量可以使用 ?P<variable>

import re

# 取出 blog 地址
a = '作者-上海悠悠 QQ交流群:717225969 blog地址:https://www.cnblogs.com/yoyoketang/ 欢迎收藏'
res = re.search(r'QQ交流群:(?P<QQ>\d+) blog地址:(?P<blog>.*?) 欢迎收藏', a)
# print(res)  # 返回Match object
print(res.groupdict())  # {'QQ': '717225969', 'blog': 'https://www.cnblogs.com/yoyoketang/'}

给要匹配的两个值添加变量,于是就可以得到字典结果了: {'QQ': '717225969', 'blog': 'https://www.cnblogs.com/yoyoketang/'}
字典取值就可以根据键值对很好的取值了

上一篇:Java中的排序(冒泡排序、选择排序)


下一篇:52 条 SQL 语句性能优化策略