天天看点

Python学习---re模块1、以下是re模块经常用到的匹配语法,没个符号都有特殊的意义,如果只是想匹配字面上的符号,则用反斜杠\转义,或者写在方括号[]里面。2、特殊表达式序列及其意义  3、创建re对象4、运用正则匹配进行搜索 5、分组匹配6、替换7、re对象的函数

python中的re模块是用来分析正则表达式的模块,re模块所提供的函数,可以用来检查所给的字符串是否与指定的正则表达式匹配。在正则表达式里用反斜杠(\)来转义特殊字符,比如'\n','\d',当然,如果厌烦了这种一段表达式里有许多反斜杠,我们也可以用r'前缀的方式来表示,在字符串前面加上r,里面的所有字符都不会被转义,此时r'\n'真的就只是\n,而不是换行符了。

1、以下是re模块经常用到的匹配语法,没个符号都有特殊的意义,如果只是想匹配字面上的符号,则用反斜杠\转义,或者写在方括号[]里面。

‘.’ 点号,在普通模式,它匹配除换行符外的任意一个字符;如果指定了 DOTALL 标记,匹配包括换行符以内的任意一个字符。
‘^’ 尖尖号,匹配一个字符串的开始,在 MULTILINE 模式下,也将匹配任意一个新行的开始
‘$’ 美元符号,表示字符串结尾。
‘*’ 星号,表示将前面的RE重复0次或多次,而且尽可能多的匹配
‘+’ 加号,表示将前面的RE重复1次或多次,而且尽可能多的匹配
‘?’ 问号,表示将前面的RE重复0次或1次,而且尽可能匹配1次
    ‘*’,‘+’等都是尽可能的匹配多次,我们称之为贪婪匹配,如果想非贪婪匹配,就在后面加‘?’,构成‘*?’, ‘+?’,,这样就能尽可能少的匹配了。
{m} m是一个数字,对于前面的RE匹配m次
{m,n} m和n都是数字,指定将前面的RE重复m到n次。注意,如果省略m,将匹配0到n个前面的RE;如果省略n,将匹配n到无穷多个前面的RE。
[] 表示一个字符集,可以单独列出字符,也可以用’-‘连接起止字符以表示一个范围。特殊字符在中括号里将失效,如+,?,$等符号。
    还可以对一个字符集合取反,以匹配任意不在这个字符集合里的字符,取反操作用一个’^’放在集合的最前面表示,放在其他地方的’^’将不会起特殊作用。例如[^1]将匹配任意不是’1’的字符;[^^]将匹配任意不是’^’的字符。
‘|’ 管道符号,经常用在组中(后面会介绍),相当于or的意思,即如果有多个匹配RE条件,用‘|’将多个条件隔开,匹配的时候就会从左至右依次匹配各个条件,需要注意的是管道符号是非贪婪匹配,即前面的条件匹配成功,后面的条件将不再进行比较。
(…) 圆括号,分组匹配,对圆括号里的RE的内容进行匹配。
(?:…) 匹配内部的RE所匹配的内容,但是不建立组。即匹配以后不能再被获取
(?#…) 注释,圆括号里的内容会被忽略。
(?= … ) 匹配表达式’…’之前的字符串,例如在字符串’pythonretest’中 (?=test) 会匹配’ pythonre’
(?!...) 匹配后面不跟表达式’…’的字符串 如果’pythonre’后面不是字符串’test’,那么 (?!test) 会匹配’ pythonre ’
(?<= … ) 匹配跟在表达式’…’后面的字符串符合括号之后的正则表达式,正则表达式’(?<=abc)def ’会在’ abcdef ’中匹配’ def ’
(?<!...) 匹配括号之后的正则表达式不跟在’…’的后面,
(?= … )与(?!...)是一对反义,只比较...前面的字符串
(?<= … )与(?<!...)是一对反义,只比较...后面的字符串
(?P<name>...) 将匹配到的字符串以name命名,作为分组名称
(?P=name) 与(?P<name>...)的用法连用,用来代指匹配,
    re.match('<(?P<name>\w*)>.*</(?P=name)>', '<h1>xxx</h2>')  #这个不匹配,因为name为h1
    re.match('<(?P<name>\w*)>.*</(?P=name)>', '<h1>xxx</h1>')  #这个匹配
在替换字符串里,如果有\g这样的写法,将匹配正则的命名组(与(?P<name>...)类似)。\g这样的写法,代表数字的组,也就是说,\g<2>一般和\2是等效的,但是万一你要在\2后面紧接着写上字面意义的0,你就不能写成\20了(因为这代表第20个组),这时候必须写成\g<2>0,另外,\g<0>代表匹配到的整个子串。
           

2、特殊表达式序列及其意义

\A 只在字符串开头进行匹配。相当于^
\b 边界分隔符,分割非字母数字和字母数字,下面会有一个例子用来理解
\B 边界分隔符,分割字母数字和字母数字,下面会有一个例子用来理解
\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_]
\Z 只在字符串结尾进行匹配。相当于$
           
# \b和\B的练习,因为这两个是对边界进行匹配的,所以与^(开始)和$(结尾)是一家人。
# \b和\B是对字符串中组成元素进行匹配的,它将字符串的组成元素分为字母数字下划线(即\w)和非字母数字下划线(即\W)两个阵营。

例子1:
string1 = "123_The 123The [email protected]#$%^&*()_+The The"
result = re.split(r'\bThe', string1)  # 这个模式的目的是将The与其前一个字符是不同阵营的字符进行分割。
print(result)  # ['123_The 123The [email protected]#$%^&*()_+', ' ', '']
# 其结果是第一个The前的字符是下划线,属于同一个阵营,所以不分割;
# 第二个The前的字符是数字,也属于同一个阵营,所以不分割;
# 第三个The前的字符是非\w的,不属于同一个阵营,所以分割了;
# 第四个The前的字符也是非\w的,不属于同一个阵营,所以分割了;

例子2:
string2 = "123_The 123The [email protected]#$%^&*()_+The The"
result = re.split(r'\bThe', string2)  # 这个模式的目的是将The与其前一个字符是同一个阵营的字符进行分割。
print(result)  # ['123_', ' 123', ' [email protected]#$%^&*()_+The The']
# 可以看到结果是完全反过来了。
           

 3、创建re对象

re.compile(pattern, flags=0):创建一个正则对象regex,这个正则对象就会被保留,方便以后使用
把正则表达式的模式和标识转化成正则表达式对象,供 match() 和 search() 这两个函数使用。
re 所定义的 flag 包括:
re.I 忽略大小写
re.L 表示特殊字符集 \w, \W, \b, \B, \s, \S 依赖于当前环境
re.M 多行模式
re.S 即为’ . ’并且包括换行符在内的任意字符(’ . ’平时匹配不包括换行符在内的所有字符)
re.X 为了增加可读性,忽略空格和’ # ’后面的注释
           

4、运用正则匹配进行搜索

# search,找到第一个返回,这个匹配地参数可以在字符串中间出现,与match区分开
re.search('kenny', 'kenny正在使用正则表达式')
targe = re.search('kenny', 'ennn答kenny正在使用正则表达式')
print(targe)  # <_sre.SRE_Match object; span=(5, 10), match='kenny'>
targe = re.search('kenny', '正在使用正则表达式')
print(targe)  # None
targe = re.search('kenny', 'kenny正在使用kenny的正则表达式')
print(targe)  # <_sre.SRE_Match object; span=(0, 5), match='kenny'>
print(targe.group())  # kenny

# match,从第一个开始匹配,若第一个字符不匹配,则不再继续匹配
targe = re.match('kenny', 'kenny正在使用正则表达式')
print(targe)  # <_sre.SRE_Match object; span=(0, 5), match='kenny'>
targe = re.match('kenny', 'ennn的kenny正在使用正则表达式')
print(targe)  # None
           

 5、分组匹配

(),括号分组
|,管道符号匹配多个分组
?,选择出现0次或1次
re.x,换行,注释
           

(1)findall

-有分组,则返回元祖列表
-无分组,则会返回字符串列表
           
regex = re.compile(r'(kenny)') 
targe = regex.findall('asdjqiokennynjafahdkennyiujzxn1234')
print(targe)  # ['kenny', 'kenny']
           

(2)split

-返回用正则分割后的列表
           
regex_1 = re.compile(r'kenny') 
print(regex_1.split('12415kenny19uidhrhuhjkenny23414'))  # ['12415', '19uidhrhuhj', '23414']
           

6、替换

(1)字符串的替换replace

s = 'sdjflsjsgkenny09709098kennysdfsf234'
ss = s.replace('kenny', '****')
print(ss)  # sdjflsjsg****09709098****sdfsf234
print(s)  # sdjflsjsgkenny09709098kennysdfsf234
           

 (2)正则的替换sub、subn

regex = re.compile(r'kenny')
s = regex.sub('***$$$$*', 'sdjflsjsgkenny09709098kennysdfsf234')
print(regex)  # re.compile('kenny')
print(s)  # sdjflsjsg***$$$$*09709098***$$$$*sdfsf234
# subn()跟上面的sub()函数一样,只是它返回的是一个元组 (新字符串, 匹配到的次数) 
sn = regex.subn('***$$$$*', 'sdjflsjsgkenny09709098kennysdfsf234')
print(sn)  # ('sdjflsjsg***$$$$*09709098***$$$$*sdfsf234', 2)
           

(3)练习

# 通过分组替换字符串格式,mm/dd/yy -> yy-mm-dd
s = '替换日期格式:10/01/2008,12/25/2018'
re_date = re.compile(r'(\d+)/(\d+)/(\d+)')
ss = re_date.sub(r'\3-\1-\2', s) # 没有名字的时候,用右斜线\3 \1 \2 分别对应上一行分组每个()的位
# 分组的时候,可以用对应位置的数字来直接表示,也可以命名,在分组内容前加上(?P<名字> 分组内容),使用的时候用\g<名字>来调用
print(ss)  # 替换日期格式:2008-10-01,2018-12-25
           
# 替换字符串中间多余空格
s = ' kenny 正则 python 好难学, 坚持一下吧,没 几个 了 '
s.strip()
re_blank = re.compile(r'\s+') # s表示空格字符。匹配任意空白字符,相当于 [ \t\n\r\f\v]
print(re_blank.sub('', s))  # kenny正则python好难学,坚持一下吧,没几个了
           

7、re对象的函数

 (1)re.escape(string) 把string中,除了字母和数字以外的字符,都加上反斜杆。

re.escape(string)把string中,除了字母和数字以外的字符,都加上反斜杆。
print(re.escape("[email protected]#$$"))  # qklwj45456\@\#\$\$
           

 (2)groups----RE所含有的组的个数。

(3)groupindex----返回一个字典,反映的是命名组的名字和序号之间的关系

terge = re.compile("(?P<name_1>\d+)-(\d+)-(?P<name_3>\d+)-(?P<name_4>\d)")
print(terge.groups)  # 4
print(terge.groupindex)  # {'name_1': 1, 'name_3': 3, 'name_4': 4}