前言
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/'}
字典取值就可以根據鍵值對很好的取值了