Python全栈工程师

24.4-Python的re模块使用

2019-10-19  本文已影响0人  BeautifulSoulpy

不必羡慕那些活的精彩快乐的人,他们其实并不比你优秀,他们只是减轻了对他人高度的感受性;从而活在自己的节奏里面;

也不要去羡慕别人的精彩,我们已经获得够没有自我了;
我们应该明白:取悦自己,永远比取悦替他人重要
一个人活在世上,必须要有真正喜爱的事情,才活的才有意义!!

总结:

  1. [\s()] []里面是或的意思;只要有就处理;
  2. subn 没有encode()方法; 元组不能被编码;返回元组;
  3. 分组() 中如果有?: 分组就不存在了,,,
  4. match、search函数可以返回match对象;findall返回字符串列表;finditer返回一个个match对象
  5. 分组与匹配各是各的; 看()包的对象是什么;
  6. groupdict() 命名分组返回字典 ,只有有名字 ?P<head> ,就可以进入到命名分组中;

Python的正则表达式

Re 模块简介

re模块是python中处理正则表达式的一个模块,通过re模块的方法,把正则表达式pattern编译成正则对象,以便使用正则对象的方法

常量
flags 说明
re.M 、 re.MULTILINE 多行模式
re.S 、re.DOTALL 单行模式
re.I 、re.IGNORECASE 忽略大小写
re.X 、re.VERBOSE 忽略表达式中的空白字符 和 # 注释
re.L 表示特殊字符集 \w, \W, \b, \B, \s, \S 依赖于当前环境
re.U 表示特殊字符集 \w, \W, \b, \B, \d, \D, \s, \S 依赖于 Unicode 字符属性数据库

使用 | 位或 运算开启 多种选项;

方法
1. re.compile(pattern[, flags]) 编译方法

语法格式为:

re.compile(pattern[, flags])

参数:
pattern : 一个字符串形式的正则表达式
flags: 可选,表示匹配模式,比如忽略大小写,多行模式等,具体参数为:

compile 函数用于编译正则表达式,生成一个正则表达式( Pattern )对象,供 match() 和 search() 这两个函数使用

正则表达式需要被编译,为了提高效率,这些编译后的结果被保存,下次使用同样的pattern的时候,就不需要再次编译。

re的其它方法为了提高效率都调用了编译方法,就是为了提速。

import re
test = 'bottle bag\nbig\napple\nAPPLE'

# 内部编译+匹配一步完成;
matcher = re.match('bot',test,re.I)   
print(matcher)
   
# 手动编译,再去对正则进行匹配; 效率高;
regex = re.compile('bot')   # 手动编译  编译后的正则表达式 
matcher = regex.match(test)   # 匹配模式
print(matcher)
#--------------------------------------------------------------------------
<re.Match object; span=(0, 3), match='bot'>
<re.Match object; span=(0, 3), match='bot'>

手动编译效率问题

手动编译的效率远远高于自动编译

import re,timeit

reg = re.compile('<(?P<tagname>\w*)>.*</(?P=tagname)>')
reg.match('<h1>xxx</h1>')

print(timeit.timeit(setup='''import re; reg = re.compile('<(?P<tagname>\w*)>.*</(?P=tagname)>')''', stmt='''reg.match('<h1>xxx</h1>')''', number=1000000))
print(timeit.timeit(setup='''import re''', stmt='''re.match('<(?P<tagname>\w*)>.*</(?P=tagname)>', '<h1>xxx</h1>')''', number=1000000))
#-------------------------------------------------------------------
0.2924321999998938
0.7150975999993534
单次匹配

(1) re.match函数
re.match 尝试从字符串的起始位置匹配一个模式,匹配成功re.match方法返回一个匹配的对象,否则返回None。

re.match(pattern, string, flags=0)
regex.match(string[, pos[, endpos]])
match匹配从字符串的开头匹配,regex对象match方法可以重设定开始位置和结束位置。返回match对象
fullmatch() 全匹配

import re
test = 'bottle bag\nbig\napple\nAPPLE'

for i,c in enumerate(test,1):
    print((i-1,c),end='\n' if i%8==0 else ' ')
print('_'*30)

regex = re.compile('b.+')   # 手动编译  编译后的正则表达式 
matcher = regex.match(test,7)   # 匹配模式, start = 7
print(matcher)
#--------------------------------------------------------------------------------------------------------
(0, 'b') (1, 'o') (2, 't') (3, 't') (4, 'l') (5, 'e') (6, ' ') (7, 'b')
(8, 'a') (9, 'g') (10, '\n') (11, 'b') (12, 'i') (13, 'g') (14, '\n') (15, 'a')
(16, 'p') (17, 'p') (18, 'l') (19, 'e') (20, '\n') (21, 'A') (22, 'P') (23, 'P')
(24, 'L') (25, 'E') ______________________________
<re.Match object; span=(7, 10), match='bag'>

(2) re.search方法
re.search 扫描整个字符串并返回第一个成功的匹配,匹配成功re.search方法返回一个匹配的对象,否则返回None

re.search(pattern, string, flags=0)
regex.search(string[, pos[, endpos]])
从头搜索直到第一个匹配,regex对象search方法可以重设定开始位置和结束位置,返回match对象

import re
test = 'bottle bag\nbig\napple\nAPPLE'

for i,c in enumerate(test,1):
    pass
    #print((i-1,c),end='\n' if i%8==0 else ' ')
print('_'*30)

regex = re.compile('b.+')   # 手动编译  编译后的正则表达式 
matcher = regex.search(test,0)   # 匹配模式 start = 1 ,end =
print(matcher)
#----------------------------------------------------
<re.Match object; span=(0, 10), match='bottle bag'>     # 返回一个match对象;

re.match与re.search的区别

re.match 只匹配字符串的开始,如果字符串开始不符合正则表达式,则匹配失败,函数返回None;
re.search 匹配整个字符串,直到找到一个匹配;

(3) re.fullmatch(pattern, string, flags=0)

regex.fullmatch(string[, pos[, endpos]])
整个字符串和正则表达式匹配

#  re.fullmatch()
import re
test = 'bottle bag\nbig\napple\nAPPLE'

for i,c in enumerate(test,1):
    pass
    #print((i-1,c),end='\n' if i%8==0 else ' ')
print('_'*30)

regex = re.compile('^b.+', re.S)   # 手动编译  编译后的正则表达式 
matcher = regex.fullmatch(test)   # 匹配模式 start = 1 ,end =
print(matcher)
#----------------------------------------------------
<re.Match object; span=(0, 26), match='bottle bag\nbig\napple\nAPPLE'>
全文搜索
(1) findall(string[, pos[, endpos]])方法 ->[]

在字符串中找到正则表达式所匹配的所有子串,并返回一个列表,如果没有找到匹配的,则返回空列表。
参数:

string : 待匹配的字符串。
pos : 可选参数,指定字符串的起始位置,默认为 0。
endpos : 可选参数,指定字符串的结束位置,默认为字符串的长度。
查找字符串中的所有数字:

import re
test = 'bottle\nbag\nbig\napple\nAPPLE\nable'

for i,c in enumerate(test,1):
    pass
    #print((i-1,c),end='\n' if i%8==0 else ' ')
print('_'*30)

matchers = re.findall('b.+', test)   # 手动编译  编译后的正则表达式 
print(matchers)
for x in matchers:
    print(type(x),x)
#---------------------------------------------------
['bottle', 'bag', 'big', 'ble']
<class 'str'> bottle
<class 'str'> bag
<class 'str'> big
<class 'str'> ble

(2) re.finditer(pattern, string, flags=0)

regex.finditer(string[, pos[, endpos]])
对整个字符串,从左至右匹配,返回所有匹配项,返回迭代器
注意每次迭代返回的是match对象

# 返回一个迭代器;
import re
test = 'bottle\nbag\nbig\napple\nAPPLE\nable'

for i,c in enumerate(test,1):
    pass
    #print((i-1,c),end='\n' if i%8==0 else ' ')
print('_'*30)

matchers = re.finditer('b.+', test)   # 手动编译  编译后的正则表达式 
print(matchers)
for x in matchers:
    print(type(x),x)
#-----------------------------------------------------
<callable_iterator object at 0x000001BC65D593C8>
<class 're.Match'> <re.Match object; span=(0, 6), match='bottle'>
<class 're.Match'> <re.Match object; span=(7, 10), match='bag'>
<class 're.Match'> <re.Match object; span=(11, 14), match='big'>
<class 're.Match'> <re.Match object; span=(28, 31), match='ble'>
匹配替换
(1) re.sub(pattern, replacement, string, count=0, flags=0)

regex.sub(replacement, string, count=0)
使用pattern对字符串string进行匹配,对匹配项使用repl替换。
replacement可以是string、bytes、function。

# 替换
import re
test = 'bottle\nbag\nbig\napple\nAPPLE\nable'

for i,c in enumerate(test,1):
    pass
    #print((i-1,c),end='\n' if i%8==0 else ' ')
print(re.sub('b\w+e','www',test).encode())  # 
#-----------------------------------------------------------------
b'www\nbag\nbig\napple\nAPPLE\nawww'
(2) re.subn(pattern, replacement, string, count=0, flags=0) ->()

regex.subn(replacement, string, count=0)
同sub返回一个元组(new_string, number_of_subs_made)

subn 没有encode()方法; 元组不能被编码;

# subn 没有encode()方法; 元组不能被编码;
import re
test = 'bottle\nbag\nbig\napple\nAPPLE\nable'

for i,c in enumerate(test,1):
    pass
    #print((i-1,c),end='\n' if i%8==0 else ' ')
print(re.subn('b\w+e','www',test))  # 
#---------------------------------------------------------
('www\nbag\nbig\napple\nAPPLE\nawww', 2)
(3) re.split(pattern, string[, maxsplit=0, flags=0])

split 方法按照能够匹配的子串将字符串分割后返回列表,它的使用形式如下:
str.split分割字符串 (默认是 \s+)

# str.split分割字符串 (**默认是 \s+**) 
import re
test = 'bottle\n\t (bag)\nbig\napple\nAPPLE\nable'

for i,c in enumerate(test,1):
    pass
    #print((i-1,c),end='\n' if i%8==0 else ' ')
print(test.split())

regex = re.compile('\s+')
print(regex.split(test))
#----------------------------------------------------
['bottle', '(bag)', 'big', 'apple', 'APPLE', 'able']
['bottle', '(bag)', 'big', 'apple', 'APPLE', 'able']

regex = re.compile('[\s()]+')
print(regex.split(test))
#----------------------------------------------------
['bottle', 'bag', 'big', 'apple', 'APPLE', 'able']
split 练习:提取每行的单词;
s = '''01 bottle
02 bag
03        big1
100         able'''

import re

print(re.split('\s+\d+\s+',s))
print(re.split('[\s\d+]+',s))
#---------------------------------------
['01 bottle', 'bag', 'big1', 'able']
['', 'bottle', 'bag', 'big', 'able']

思路总结:
1. 前面补字符(空格)法;

分组()

() 中如果有?: ,分组就不存在了,,,

使用小括号的pattern捕获的数据被放到了组group中。
match、search函数可以返回match对象;findall返回字符串列表;finditer返回一个个match对象

如果pattern中使用了分组,如果有匹配的结果,会在match对象中

  1. 使用group(N)方式返回对应分组,1到N是对应的分组,0返回整个匹配的字串
  2. 如果使用了命名分组,可以使用group('name')的方式取分组
  3. 也可以使用groups()返回所有组
  4. 使用groupdict() 返回所有命名的分组
# 分组
import re
test = 'bottle\n\t (bag)\nbig\napple\nAPPLE\nable'

for i,c in enumerate(test,1):
    pass
    #print((i-1,c),end='\n' if i%8==0 else ' ')
print('-'*30)

regex = re.compile('(b\w+)')    # 分组包 match对象,groups就是(match,)
result = regex.finditer(test)
for x in result:
    print(x,x.groups())
#-----------------------------------------------------------
<re.Match object; span=(0, 6), match='bottle'> ('bottle',)
<re.Match object; span=(10, 13), match='bag'> ('bag',)
<re.Match object; span=(15, 18), match='big'> ('big',)
<re.Match object; span=(32, 35), match='ble'> ('ble',)

1. 分组与匹配各是各的; 看()包括的对象是什么;
regex = re.compile('a?(b\w+)')    # 分组包 match对象,groups就是(match)
result = regex.finditer(test)
for x in result:
    print(x,x.groups())
#-------------------------------------------------------
<re.Match object; span=(31, 35), match='able'> ('ble',)             # match='able'>     groups= ('ble',)      

2. 分组号 0->matcher  ; 1->分组1     


3. 命名分组,只有有名字 ?P<head>  ,就可以进入到命名分组中;
import re
test = 'bottle\n\t (bag)\nbig\napple\nAPPLE\nable'

for i,c in enumerate(test,1):
    pass
    #print((i-1,c),end='\n' if i%8==0 else ' ')
print('-'*30)

regex = re.compile('(?P<head>a)(?P<tail>b\w+)')    # 分组包 match对象,groups就是(match)
result = regex.search(test)
print(result.groups())
print(result.group(0),result.group(1),result.group(2))
print(result.groupdict())
#-----------------------------------------------
('a', 'ble')
able a ble
{'head': 'a', 'tail': 'ble'}

上一篇下一篇

猜你喜欢

热点阅读