一、元字符
字符组是元字符中的一个。在字符组中所有的字符都可以匹配任意一个字符位置上能出现的内容,如果在字符串中有任意一个字符是字符组中的内容,那么就是匹配上的项。
[0-9] [a-z] [A-Z] ascii编码小的值,指向一个大的值
# \d表示匹配一个数字 [0-9]
元字符:
\w word匹配字母和数字、下划线 \d digit \s space \n next \t tab \W \D \S
^开始 $结尾 \b 匹配边界
[] [^] 字符组相关的
| 或
() 分组
. 匹配除了换行符之外的任意字符
二、量词
?0次或1次,+1次或多次 *0次或多次 {n}n次 {n,}n次或多次 {n,m}n次或m次
\d+整数
\d+\.\d+ 小数
\d+\.\d+|\d+ 整数或者小数 \d+(\.\d+)?
# 贪婪匹配 : 正则会尽量多的帮我们匹配
# 默认贪婪 回溯算法
# 非贪婪匹配 :会尽量少为我们匹配
# 量词?表示非贪婪 惰性匹配
# .*?x 表示匹配任意长度任意字符遇到一个x就立即停止
元字符注意事项: 元字符 量词
元字符 量词 ? 在量词的范围内尽量少的匹配这个元字符
分组 对某些固定的内容做量词约束
或 把长的放前面
转义符
pattern = r'\\n'
s = r'\n'
转义:使用 \或r转义
三、re模块
3.1 findall
import re
# findall
ret = re.findall('\d+','SGY93SHD2183Y0')
print(ret)
结果:
['', '', '']
参数 正则表达式 待匹配的字符串
返回值 是一个列表 所有匹配到的项
没有匹配到会返回一个空列表
如果遇到分组,findall会优先显示分组中的内容
(?:正则表达式)取消分组优先
3.2 search
import re
# search
ret = re.search('\d+','SGY93SHD2183Y0')
print(ret)
print(ret.group())
结果:
<_sre.SRE_Match object; span=(3, 5), match=''> # 对象
93
返回值 : 返回一个SRE_Match对象 ,没有匹配到会返回None,没有.group()方法。如果有分组,通过索引取各分组中的内容
通过group去取值
且只包含第一个匹配到的值
findall 有个特点,会优先显示分组中的内容。优先前面的
import re
ret = re.findall('(www)\.(baidu|oldboy)\.(com)','www.baidu.com')
print(ret) # [('www', 'baidu', 'com')]
search的特点:
import re
ret = re.search('(www)\.(baidu|oldboy)\.(com)', 'www.baidu.com')
print(ret.group(0)) # www.baidu.com
print(ret.group(1)) # www
print(ret.group(2)) # baidu
print(ret.group(3)) # com
match 验证用户输入的内容
ret = re.match('\d+','25ahs293djjk293sahf2938u')
print(ret) # <_sre.SRE_Match object; span=(0, 2), match='25'>
print(ret.group()) # 25
查看字符串开始位置的数字是多少,索引分别是多少。
分割split的用法
import re
s = 'alex8123egon1120boss_jin'
ret = re.split('\d+',s)
print(ret) # ['alex', 'egon', 'boss_jin'] ret = re.split('(\d+)',s) # (\d)+ \d\d\d\d\d...(\d)
print(ret) # ['alex', '8123', 'egon', '1120', 'boss_jin'] ret = re.split('\d(\d)',s)
print(ret) # ['alex', '1', '', '3', 'egon', '1', '', '0', 'boss_jin']
替换sub
s = 'alex|egon|boss|jin'
print(s.replace('|','')) # alexegonbossjin s1 = 'alex8123egon1120boss_jin626356'
ret = re.sub('\d+','|',s1)
print(ret) # alex|egon|boss_jin| ret = re.sub('\d+','|',s1,1)
print(ret)
#alex|egon1120boss_jin626356 替换一次 ret = re.subn('\d+','|',s1)
print(ret) # ('alex|egon|boss_jin|', 3) 元组,并显示次数
compile 编译正则规则
import re
com = re.compile('\d+') # 制定正则规则
ret = com.search('abc1cde2fgh3skhfk')
print(ret.group()) # ret = com.findall('abc1cde2fgh3skhfk')
print(ret) # ['1', '2', '3'] ret = com.finditer('abc1cde2fgh3skhfk')
for i in ret:
print(i.group()) # 1 2 3
finditer 节省空间的方法
ret = re.finditer('\d+','abc1cde2fgh3skhfk')
print(ret)
for i in ret:
print(i.group()) # 逐个取值
四、分组命名、分组约束
当我们需要取 <h1>函数</h1> \<a>函数</a> 中的内容时,需要用到分组命名:
pattern = '<(?P<tag>.*?)>.*?</(?P=tag)>'
ret = re.search(pattern,'<h1>函数</h1>')
print(ret) # <_sre.SRE_Match object; span=(0, 11), match='<h1>函数</h1>'>
if ret:
print(ret.group()) # <h1>函数</h1>
print(ret.group(1)) # h1
print(ret.group('tag')) # h1
可以去除类似 <h1>函数</h1> 标签对
直接用\1也是可以的
pattern = r'<(.*?)>.*?</\1>'
ret = re.search(pattern,'<a>函数</a>')
print(ret) # <_sre.SRE_Match object; span=(0, 11), match='<h1>函数</h1>'>
if ret:
print(ret.group()) # <h1>函数</h1>
print(ret.group(1)) # h1