yiruia的个人博客分享 http://blog.sciencenet.cn/u/yiruia

博文

Day19 re模块

已有 1521 次阅读 2020-3-15 21:52 |系统分类:科研笔记

python中的re模块

re模块为python中的内置模块,python程序中通过这个模块来使用正则表达式

re模块的使用

re模块有两种使用方式,示例中以match方法为例

方式1:

步骤:

(1)直接使用re.match方法(传入正则表达式和需要匹配的字符串)对文本进行匹配查找,match方法返回一个match方法。

(2)使用match对象提供的方法获取匹配结果。

import re
m = re.match(r'\d+','123abc234') # 返回一个match对象
print(m.group()) #输出匹配结果:123


match从头开始匹配,如果正则规则从头开始可以匹配上,就返回一个变量,匹配的内容需要用group才能显示,如果没有匹配上就返回None,使用group()就会报错。

ret = re.match('[a-z]+','eva egon yuan')
if ret:
    print(ret.group()) # 输出结果为:eva

方法2:

步骤:

(1)使用re.compile方法(传入正则表达式)得到pattern对象

(2)通过pattern对象提供的方法对字符串进行匹配查找,返回一个mathch对象(包含了匹配结果)

(3)使用match对象提供的方法获取匹配结果

import re
pattern = re.compile(r'\d+') # 返回一个pattern对象
m = pattern.match('123abc456') # 返回一个match对象
print(m.group()) #输出匹配结果:123


如上2种方法的区别在于,第二种方式通过re.compile方法获取pattern对象,使得一个正则表达式被多次用于匹配;而第一种方式,每一次匹配都需要传入正则表达式。

compile方法

re.compile(pattern[, flag])

示例中的compile方法用于编译正则表达式,返回一个pattern对象,可利用pattern对象中的一系列方法对字符串进行匹配查找。pattern对象中的常用方法包括:match、search、findall、finditer、split、sub、subn。当然这些方法可以使用re模块直接调用

import re
obj=re.compile('\d{3}')
# 将正则表达式编译成一个正则表达式对象,规则要匹配的是3个数字
ret = obj.search('abc123ee456ee')
# 正则表达式对象调用search,参数为待匹配字符串
print(ret.group()) # 结果:123

match方法

match方法用于从字符串的头部开始匹配,仅返回第一个匹配的结果

pattern.match(string[,pos[,endpos]])或re.match(pattern,string[,flags])

pattern.match(string[,pos[,endpos]])中的pos,endpos指定字符串匹配的起始和终止位置,这两个均为可选参数,若不指定,默认从字符串的开头开始匹配。

re.match(pattern,string[,flags])中的pattern为传入的正则表达式,flags指定匹配模式,如忽略大小写,多行模式,同compile方法中的flag参数。

分组匹配

可以通过在正则表达式中使用小括号'()',来对匹配到的数据进行分组,然后通过group([n]),groups()获取对应的分组数据。

import re
pattern = re.compile('([0-9]*)([a-z])*([0-9])*')
m = pattern.match('123abc456')
# 输出匹配的完整字符串
print(m.group()) # 123abc456
# 同上,输出匹配的完整字符串
print(m.group(0)) # 123abc456
# 从匹配的字符串中获取第一个分组
print(m.group(1)) # 123
# 从匹配的字符串中获取第二个分组
print(m.group(2)) # abc
# 从匹配的字符串中获取第三个分组
print(m.group(3)) # 456
# 从匹配的字符串中获取所有分组,返回元组
print(m.groups()) #  ('123', 'abc', '456')
# 获取第二个分组在字符串中的起始位置(分组第一个字符的索引),start方法的默认参数为0,即字符串的起始索引
print(m.start(2)) # 3
# 获取第二个分组在字符串中的终止位置(分组最后一个字符的索引+1),通过start方法,end方法的默认参数也为0,即字符串结尾的索引+1
print(m.end(2))
# 第三个分组的起始和结束位置,即(start(3),end(3))
print(m.span(3)) # (6,9)
# 同(start(),end())
print(m.span()) #(0,9)

上述中的group(),groups(),start(),end(),span()方法均为match类中的方法,这些方法用于从匹配的字符串中(或者说是从match对象中)获取相关信息。

re模块下的常用方法

re模块中较为常用的方法除了compile()和match()方法,还有下面列出的这些:

search方法

不同于match方法的从头开始匹配,search方法用于在字符串中的进行查找(从左到右进行查找),只要能找到一个匹配结果,就返回Match对象,若没有则返回None~

search(string[,pos[,endpos]]) #可选参数用于指定查找的起始位置和结束位置,默认pos为0,endpos为字符串长度

示例:re.search

import re
pattern = re.compile(r'[a-z]+')
m = pattern.match('123abc456cde')
print(m) # None
m = pattern.search('123abc456cde')
print(m.group()) # abc

由于match是从头开始匹配,所以这里匹配不到结果

findall方法

match方法和search方法仅会返回一个结果,findall方法会将字符串中的所有匹配结果以列表的形式返回,注意,返回的是列表,不是match对象。

findall(strin[,pos[,endpos]])  # 可选参数pos,endpos用于指定查找的起始位置和结束位置,默认pos为0,endpos为字符串长度。

import re
pattern = re.compile(r'[a-z]+')
m = pattern.findall('123abc456cde')
print(m) # ['abc', 'cde']

findall方法的有限级查询,findall方法会优先把匹配结果组里的内容进行返回。

import re
pattern = re.compile('\d([a-z]+)\d')
m = pattern.findall('123abc456cde')
print(m) # ['abc']
import re
pattern = re.compile('\d[a-z]+\d')
m = pattern.findall('123abc456cde')
print(m) # ['3abc4']

其实我们想要的结果是‘3abc4’,但是findall方法会优先返回分组中的内容,即'abc'。若想要匹配结果,取消权限即可,就是在小括号的起始位置加上'?:'

import re
pattern = re.compile('\d(?:[a-z])+\d')
m = pattern.findall('123abc456cde')
print(m) # ['3abc4']

finditer方法

finditer 方法与 findall方法类似,会查找整个字符串并返回所有匹配的结果,返回的是一个迭代器,且每一个元素为 Match 对象~

import re
pattern = re.compile('\d+')
m = pattern.finditer('123abc456cde')
for i in m:
    print(i.group())
'''
123
456
'''

split方法

split方法用于将字符串进行切割,切割使用的分隔符就是字符串中被匹配到子串,将被切割后的子串以列表的形式返回。

split(string[,maxsplit]) #maxsplit参数用于指定最大分割次数,默认会将这个字符串分割

import re
pattern = re.compile(r'\d+')
m = pattern.split('123abc456cde')
print(m)
'''
['', 'abc', 'cde']
'''

正则表达式中添加括号后,会保留分隔符

import re
pattern = re.compile('(\d+)')
m = pattern.split('123abc456cde')
print(m)
'''
['', '123', 'abc', '456', 'cde']
'''

sub方法

sub方法用于将字符串中匹配的子串替换为指定的字符串

pattern.sub(repl, string[, count])
或者re.sub(pattern, repl, string[, count])

count为可选参数,指定最大替换次数,repl可以是一个字符串,也可以是一个\id引用匹配到的分组(但不能使用\0),还可以是一个方法,该方法仅接受一个参数(Match对象),且返回一个字符串。

import re
m = re.sub('\d+','###','123abc456cde')
print(m)
'''
###abc###cde
'''

repl是一个分组引用

将类似于‘hello world’这样的字符串前后两个单词替换

import re
ret = re.sub(r'(\w+) (\w+)', r'\2 \1', 'hello world; hello kitty')
print(ret)

'''
world hello; kitty hello
'''

3)repl是一个方法

import redef func(m):
    return 'hi' + ' ' + m.group(2)

ret = re.sub(r'(\w+) (\w+)', func, 'hello world; hello kitty')
print(ret)# 输出结果:hi world; hi kitty

subn方法

subn方法和sub方法类似,subn方法会返回一个元组,元组有两个元素,第一个元素与sub方法返回的结果一致,第二个元素为字符串中被替换的子串个数

import redef func(m):
    return 'hi' + ' ' + m.group(2)

ret = re.subn(r'\d+', '###', 'abc123cde')
print(ret)

ret = re.subn(r'(\w+) (\w+)', r'\2 \1', 'hello world; hello kitty')
print(ret)

ret = re.subn(r'(\w+) (\w+)', func, 'hello world; hello kitty')
print(ret)
# 输出结果:('abc###cde', 1)
('world hello; kitty hello', 2)
('hi world; hi kitty', 2)

贪婪匹配和非贪婪匹配

正则匹配默认使用的激素hi贪婪匹配,也就是尽可能多的匹配,如下示例为贪婪匹配:

import re
m = re.match('\d+','123abc456cde')
print(m.group())
# '''
123
# '''

同一示例中使用非贪婪匹配,在正则后面加上一个'?'即可,注意这个问好不是代表0个或者1个(注意区分):

import re
m = re.match('[a-z]+?', 'abc123def')
print(m.group())
'''
a
'''

贪婪匹配(旦旦使用?),?重复0个或者1个,贪婪匹配下匹配一个

import re
ret=re.findall('13\d?','1312312312, 134, 34234, 2313')
print(ret)
'''
['131', '134', '13']
'''

惰性匹配示例:

import re
ret=re.findall('131\d+?','1312312312')
print(ret)
'''
['1312']
'''

正则表达式补充

转义符\

1、反斜杠后边跟元字符去除特殊功能,比如:

2、反斜杠后边跟普通字符实现特殊功能,比如\d

\d  匹配任何十进制数;      它相当于类 [0-9]。
\D  匹配任何非数字字符;    它相当于类 [^0-9]。
\s  匹配任何空白字符;      它相当于类 [ \t\n\r\f\v]。
\S  匹配任何非空白字符;    它相当于类 [^ \t\n\r\f\v]。
\w  匹配任何字母数字字符;   它相当于类 [a-zA-Z0-9_]。
\W  匹配任何非字母数字字符; 它相当于类 [^a-zA-Z0-9_]\b  匹配一个特殊字符边界,比如空格 ,&,#等

让我们看一下\b的应用

import re
ret=re.findall(r'I\b','I love you')
print(ret)
'''
['I']
'''

tip:

如上示例中

ret=re.findall(r'I\b','I love you')

使用的是r'I\b'而不能使用'I\b',解释如下:

python程序在这里的执行过程分为两步:

第一步:python解释器读取‘I\b’字符串进行解析,解析完成后传递给re模块

第二步:re模块对接收到的字符串进行解析

在第一步中,'\b' 和 '\n' 类似,对于Python解释器而言,有特殊的意义,Python解释器针对 '\b' 和 '\n' 会根据ASCII码表进行翻译,翻译完成之后再传递给 re 模块进行后续的处理;所以 re 模块获取到的不会是 原模原样的 'I\b'。这里若要让 re 模块接收到原模原样的 'I\b',有两种方式:

1)在字符串中使用 \ ,将 \b 转义
    re.findall('I\\b','I am LIST')2)直接在字符串前面加 r,使字符串中的 \b 失效,建议使用这种方式
    re.findall(r'I\b','I am LIST')

还有一种情况,要匹配的字符串本身就包含 '\'  , 例如匹配 'hello\kitty' 中的 'o\k'
分析:\ 对于re 模块而言,有转义的意思,所以 re 模块希望获取到的字符串规则是 'o\k',也就是说Python解释器解析完字符串后传递给 re 模块的是 'o\k'(如果直接使用 re.findall('o\k','hello\kitty') ,re模块获取到的是 'o\k'),所以这里也有两种实现方式:

1)re.findall(r'o\\k','hello\kitty') ,建议使用这种方式
2)针对2个 \ 分别进行转义
     re.findall('o\\\\k','hello\kitty')

元字符之|

|表示 或者,使用 | 时一般需要和 括号配合使用,不然无法区分 | 的左边与右边

import re
ret = re.search('(ab)|\d','#@123abc')    # 匹配 ab 或者 数字,search仅会返回第一个匹配到的
print(ret.group())
'''
1
'''

字符集[]的是使用

import re
# [bc] 表示仅匹配 b 或者 c,如下示例中表示,匹配 abd 或者 acd 
ret = re.findall('a[bc]d','acd') 
print(ret)   #['acd']
# [a-zA-Z] : 所有大小写字母# [a-zA-Z0-9] : 所有大小写字母及数字
# [a-zA-Z0-9_] : 所有大小写字母及数字,再加上一个下划线ret = re.findall('[a-z]','acd')    # 匹配所有小写字母print(ret)   #['a', 'c', 'd']# 注意:元字符在 字符集[] 中没有任何效果,这里的 . 和 + 就是普通的符号,有效果的元字符包括:- ^ \ret = re.findall('[.*+]','a.cd+')    
print(ret)   
#['.', '+']
# - 表示范围符号ret = re.findall('[1-9]','45dha3')    
# 匹配数字 1 至 9print(ret)   #['4', '5', '3']

 # ^ 表示取反,即匹配 非a,非b的字符ret = re.findall('[^ab]','45bdha3')   
print(ret)   #['4', '5', 'd', 'h', '3']
# \ 为转义符ret = re.findall('[\d]','45bdha3')     
print(ret)   #['4', '5', '3']




https://blog.sciencenet.cn/blog-3405644-1223696.html

上一篇:Day18正则表达式
下一篇:Day20 常用模块
收藏 IP: 223.91.42.*| 热度|

0

该博文允许注册用户评论 请点击登录 评论 (0 个评论)

数据加载中...

Archiver|手机版|科学网 ( 京ICP备07017567号-12 )

GMT+8, 2024-5-20 05:20

Powered by ScienceNet.cn

Copyright © 2007- 中国科学报社

返回顶部