python基于re模块的正则表达式
正则表达式
re.match方法
re.match尝试从字符串的起始位置匹配一个规则,匹配成功返回match对象,否则返回None。可以使用group()获取匹配成功的字符串
-
语法:
re.match(pattern, string, flags = 0) -
参数:
参数 描述 pattern 匹配的正则表达式 string 要匹配的字符串 flags 设置匹配方式 -
flags属性:
修饰符 描述 re.I 不区分大小写 re.S 元字符( . )可以匹配行 re.M 可以匹配到每一行开头影响^和$ re.X 给正则添加注释 re.U 根据Unicode字符集解析,影响\w \W \b \B
同时使用多个标志位可以使用 | 连接如:re.I | re.M
-
使用group(num)或者groups()匹配对象函数获取表达式
匹配对象的方法 描述 group(num=0) 匹配的整个表达式的字符串, group0可以一次输入多个组号,在这种情况下它将返回一个包含那些组所对应值的元组。 groups() 返回一个包含所有小组字符串的元组,从1到所含的小组号
import re
str = 'python is the best language in the world'
# match 只能匹配以 XXX 开头的字符串,第一个参数是正则,第二个是需要陪陪的字符串
result = re.match('(.*) is (.*?) .*', str, re.I|re.M)
if result :
print('匹配成功!!')
print(result)
print(result.group()) # 匹配成功使用group方法取出字符串
print(result.group(1)) # 返回匹配成功的元组的第二项
print(result.group(2))
print(result.group(0))
print(result.groups())
else:
print('匹配失败!!')
print(result)
# print(result.group()) # 匹配失败,返回None 没有group()函数
运行结果:
# 匹配成功!!
<re.Match object; span=(0, 40), match='python is the best language in the world'>
python is the best language in the world
python
the
python is the best language in the world
('python', 'the')
正则表达式匹配规则
匹配字符
| 符号 | 匹配规则 |
|---|---|
| . | 匹配任意1个字符除了换行符\n |
| [abc] | 匹配abc中的任意一个字符 |
| \d | |
| \s | 匹配空白,即空格,tab键 |
| \S | 匹配非空白,除空格,tab键之类的 |
| \w | 匹配单词字符,即a-z、A-Z、0-9、_ |
| \W | 匹配非单词字符 |
. 的使用
匹配除了\n的任意一个字符
import re
names = '李达','李明','小王','小李','李\n'
# .的使用
pattern = '李.'
for name in names:
res = re.match(pattern,name)
if res is not None:
print(res.group())
pass
# 结果:
# 李达
# 李明
# 不能匹配大数字
[]的使用
匹配括号内的一个字符可以用-表示范围:[a-z] [A-Z] [0-9a-zA-Z]
import re
names = 'hello','gold','kold','eello','qq\n'
# .的使用
pattern1 = '[heq]....'
for name in names:
res = re.match(pattern,name)
if res is not None:
print(res.group())
pass
# 结果:
# hello
# eello
\d \D
\d 匹配一个数字 0-9
\D 匹配一个非数字
import re
names = 'hello','gold','kold','eello','qq\n','1ghjj',' hhh', \
'\tvbn'
# \d \D的使用
pattern1 = '\d....'
pattern2 = '\D....'
for name in names:
res1 = re.match(pattern1,name)
res2 = re.match(pattern2,name)
if res1 is not None:
print('\d 的结果%s'%(res1.group()))
pass
if res2 is not None:
print('\D 的结果%s'%(res2.group()))
pass
# 结果:
# \D 的结果hello
# \D 的结果eello
# \d 的结果1ghjj
\s \S的使用
匹配一个空白字符(\n \t)
import re
names = 'hello', 'gold', 'kold', 'eello', 'qq\n', '1ghjj', ' hhh', \
'\tvbn', '\nnmn'
# \d \D的使用
pattern1 = '\s...'
pattern2 = '\S...'
for name in names:
res1 = re.match(pattern1, name)
res2 = re.match(pattern2, name)
if res1 is not None:
print('\s 的结果%s' % (res1.group()))
pass
if res2 is not None:
print('\S 的结果%s' % (res2.group()))
pass
# 结果:
# \S 的结果hell
# \S 的结果gold
# \S 的结果kold
# \S 的结果eell
# \S 的结果1ghj
# \s 的结果 hhh
# \s 的结果 vbn
# \s 的结果
# nmn
\w \W 的使用
\w匹配字母、数字、下划线,即 a-z,A-Z,0-9,_
\W匹配不是字母、数字、下划线
import re
names = 'hello', 'gold', 'kold', 'eello', 'qq\n', '1ghjj', ' hhh', \
'\tvbn', '\nnmn'
print(names)
# \d \D的使用
pattern1 = '\w...'
pattern2 = '\W...'
for name in names:
res1 = re.match(pattern1, name)
res2 = re.match(pattern2, name)
if res1 is not None:
print('\w的结果%s' % (res1.group()))
pass
if res2 is not None:
print('\W的结果%s' % (res2.group()))
pass
# 结果:
# ('hello', 'gold', 'kold', 'eello', 'qq\n', '1ghjj', ' hhh', '\tvbn', '\nnmn')
# \w的结果hell
# \w的结果gold
# \w的结果kold
# \w的结果eell
# \w的结果1ghj
# \W的结果 hhh
# \W的结果 vbn
# \W的结果
# nmn
匹配限定符号
| 符号 | 描述 | 符号 | 描述 |
|---|---|---|---|
| * | 匹配零次或多次 | 重复 m 次 | |
| + | 匹配一次或多次 | 重复 m 到 n 次,其中 n 可以省略,表示 m 到任意次 | |
| ? | 匹配一次或零次 | 至少 m 次 |
1、*号的使用
将* 前面的字符匹配0~无穷次
print(re.match('[a-z]*','Any'))不会报错因为会匹配0次
import re
strs = "AnybvjdfviniIj"
print(strs)
# *
pattern1 = '[A-Z][a-z]*'# 将[a-z]匹配0-无数次
res1 = re.match(pattern1, strs)
if res1 is not None:
print('[A-Z][a-z]*的结果%s' % (res1.group()))
pass
# 结果
# AnybvjdfviniIj
# [A-Z][a-z]*的结果Anybvjdfvini
2、+号的使用
与*号类似,匹配至少一次
print(re.match('[a-z]*','Any'))会报错因为会匹配1次,而字符串里没有
print(re.match("[a-z_]+",'asd').group())
3、? 号的使用
? 前面的字符最多出现一次
import re
print(re.match("[a-z_]?",'asd').group())
# 结果
# a
4、{min.max}的使用
匹配前面的字符min~max次
import re
str = '123abc'
pattern1 = '\d{3}' # 精确匹配三次
pattern2 = '\d{1,2}' # 至少匹配1次,最多2次
pattern3 = '\d{2,}' # 至少匹配2次
result1 = re.match(pattern1, str)
result2 = re.match(pattern2, str)
result3 = re.match(pattern3, str)
print(result1.group())
print(result2.group())
print(result3.group())
# 结果
# a
一个小例子:匹配邮箱 xxxxx@163.com
import re
str = input("请输入您的邮箱:")
pattern1 = '[a-zA-Z0-9]{3,}@163.com' # 精确匹配三次
result1 = re.match(pattern1, str)
if result1 is not None :
print(result1.group())
else:
print('邮箱格式错误')
pass
原生字符串
在大多数编程语言相同,正则表达式里使用“\”作为转义字符,这就可以能 造成反斜 杠困扰。示例如下:
path = 'C:\\a\\b\\c'
print(path)
# 结果 :C:\a\b\c
在python语言之中如果要匹配 '\'
import re
s = 'c:\\a\\b\\c'
# m=re.match('c:\\a\\b',s) #无法匹配到
# 需要 4 个反斜杠“\\\\”:前面两个和后两个分别用于在编程语言里
# 转义成反斜杠,转换成两个反斜杠后再在
# 正则表达式里转义成一个反斜杠
m = re.match('c:\\\\a\\\\b', s)
if m is not None:
print('匹配的结果 1:', m.group())
else:
print('无法匹配')
# 结果:
# 匹配的结果 1: c:\a\b
python提供了修饰符'r'表示不需要转义
import re
str = 'c:\\a\\b\\c'
str_r = r'c:\e\f\g\h'
m = re.match('c:\\\\a\\\\b', str)
m2 = re.match(r'c:\\e\\f\\g',str_r)
m3 = re.match(r'c:\\a\\',str)
print(m.group())
print(m2.group())
print(m3.group())
# 结果:
# c:\a\b
# c:\e\f\g
# c:\a\
总结
r的使用是的原本需要写成 \\b \t的匹配规则直接可以写作:r'\b'
边界字符
1、^ $的使用:
- ^ 表示必须以后面的所有字符开头
import re
str = '12345687@qq.com'
str1 = '1248437598@qq.com'
pattern = '^123\d*@qq.com'
m = re.match(pattern, str)
m1 = re.match(pattern,str1)
print(m.group())
print(m1.group())
# 结果:
# 12345687@qq.com
# Traceback (most recent call last):
# File "e:/ZOEDestop/bgImg/正则表达式.py", line 10, in <module>
# print(m1.group())
# AttributeError: 'NoneType' object has no attribute 'group'
- $表示必须以前面的所有字符结尾
import re
str = '1234567@qq.com'
str1 = '1248_8@qq.com'
pattern = '[^8]*@\w{2,10}.com$' #[^]8所有字符除了8
m = re.match(pattern, str)
m1 = re.match(pattern,str1)
print(m.group())
print(m1.group())
# 1234567@qq.com
# Traceback (most recent call last):
# File "e:/ZOEDestop/bgImg/正则表达式.py", line 10, in <module>
# print(m1.group())
# AttributeError: 'NoneType' object has no attribute 'group'
\b \B的使用
\b 匹配一个单词的边界
\B 匹配非单词的边界
- \b 匹配一个单词的边界
- XXX\b -- 匹配每个单词必须要以XXX结尾
- \bxxx -- 匹配的每个单词必须要以xxx开头
import re
# 从右边开始匹配**单词与符号之间**是否满足规则,满足则输出整个字符串
# 不满足则继续匹配下一个下一个边界
# 下面的str1为例:匹配第一个边界为:'yurifgucom weew_com tyuo_com1'的最右边不满足
# 匹配第二个边界为:'yurifgucom weew_com' 满足输出
str = 'yurifgucom weew_com tyuo_com1'
str1 = '1248_8@qq.com1 erg'
pattern = r'.*com\b'
m = re.match(pattern, str)
m1 = re.match(pattern,str1)
print(m.group())
print(m1.group())
# 结果:
# yurifgucom weew_com
# Traceback (most recent call last):
# File "e:/ZOEDestop/bgImg/正则表达式.py", line 20, in <module>
# print(m1.group())
# AttributeError: 'NoneType' object has no attribute 'group'
- \B = [^\b] 匹配非单词边界(单词与单词、字符与字符之间的边界)也即:每个字母与字母之间、符号与符号之间,不包括字母与符号
import re
#\B为非单词边界 单词语单词 符号与符号之间额边界
pattern = r'.*\Bab'
# 类似于\b \B从右边开始匹配第一个非单词边界(下面用**↑**)标识
# 'v↑b↑h↑a↑b a↑b #↑#a↑b↑a↑b#a↑b'
v = re.match(pattern, 'vbhab ab ##abab#ab')
print(v)
# ab 不为右边界
pattern = r'.*ab\B'
v = re.match(pattern, 'wabe')
print(v)
# 结果:
# <re.Match object; span=(0, 15), match='vbhab ab ##abab'>
# <re.Match object; span=(0, 3), match='wab'>
分组匹配
分组匹配的规则:
| 符号 | 匹配规则 |
|---|---|
| | | 匹配左右任意一个表达式 |
| (ab) | 将括号中字符作为一个分组 |
| \num | 引用分组num匹配到的字符串 |
| (?P) | 分组起别名(必须大写) |
| (?P=name) | 引用别名为name分组匹配到的字符串 |
- |的使用
import re
# 匹配出0-199之间的数字
# |前是一个规则,后也是一个规则,在匹配时前面规则不满足才会匹配下一个规则
rex = r'^1\d\d|\d?\d$'
while True:
match_str = input("输入一个字符串:")
if match_str == 'no':
break;
pass
print(re.match(rex,match_str))
# 结果:
# 输入一个字符串:456
# None
# 输入一个字符串:45
# <re.Match object; span=(0, 2), match='45'>
# 输入一个字符串:56
# <re.Match object; span=(0, 2), match='56'>
# 输入一个字符串:789
# None
# 输入一个字符串:0
# <re.Match object; span=(0, 1), match='0'>
# 输入一个字符串:2
# <re.Match object; span=(0, 1), match='2'>
# 输入一个字符串:no
- () 和 \num 的使用
import re
# 匹配一个html标签
str_html = '<html><br>你好啊</br></html>'
# <(.*)> <>内的内容必须要使用()因为如果不使用后面的\num无法找到
# 对应的匹配的标签 (</\2>)的括号可不写
rex_html = r'<(.*)><(.*)>(.*)(</\2>)(</\1>)'
res = re.match(rex_html, str_html)
print(res)
# 结果 :<re.Match object; span=(0, 25),
# match='<html><br>你好啊</br></html>'>
print(res.group(0)) # 结果 : <html><br>你好啊</br></html>
print(res.group(1)) # 结果:html 组一的结果
print(res.group(2)) # 结果 :br 组二的结果
- (?P<要起的别名>) (?P=起好的别名)
import re
# 匹配一个html标签
#
str_html = '<html>-<br>你好啊</br>-</html>'
rex_html = r'<(?P<name1>.*)>-<(?P<name2>.*)>.*</(?P=name2)>-</(?P=name1)>'
print(re.match(rex_html, str_html))
# 结果:
# <re.Match object; span=(0, 27), match='<html>-<br>你好啊</br>-</html>'>
re模块的方法
re.compile方法
- compile将正则表达式模式编译成一个正则表达式对象
- reg = re.compile(pattern)
result = reg.match(string) - 等效于 result= re.match(pattern, string)
- 使用 recompile()和保存所产生的正则表达式对象重用效率更高
- reg = re.compile(pattern)
from time import *
# 使用compile一次编译可以使用无数次提高了效率
rexed = re.compile(r'(\d?\d)$')
begin_time = time()
count = 1000000
while count:
count -= 1
rexed.match('89')
pass
end_time = time()
print(end_time - begin_time)
count = 1000000
rex_str = r'(\d?\d)$'
begin_time = time()
while count:
count -= 1
re.match(rex_str,'89')
pass
end_time = time()
print(end_time - begin_time)
# 结果:
# 0.49109530448913574
# 1.1046862602233887
re.search 方法
search 在一个字符串中搜索满足文本模式的字符串。语法格式如下:
re.search(pattern, string, flags=0)
search 函数参数说明:
| 参数 | 描述 |
|---|---|
| pattern | 匹配的正则表达式 |
| string | 要匹配的字符串 |
| flags | 标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。如下表列出正则表达式修饰符一可选标志,同re.match() |
| search() 与 match() 类似 | |
| search() 会在字符串内寻找可以匹配的且只匹配一次 | |
| match() 会在字符串的开头匹配不成功则返回None |
import re
print(re.match("you","you are yourself"))
# <re.Match object; span=(0, 3), match='you'>
print(re.match("are","you are yourself"))
# None
print(re.search("you","you are yourself"))
# <re.Match object; span=(0, 3), match='you'>
print(re.search("are","you are yourself"))
# <re.Match object; span=(4, 7), match='are'>
re.findall
在字符串中找到正则表达式所匹配的所有子串,并返回一个列表,如果没有找到匹配的, 则返回空列表。语法格式如下:
findall(pattern, string, flags=0)
pattern 匹配的正则表达式
string 要匹配的字符串。
flags 标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。如下表列出正则表达式修饰符一可选标志
import re
pattern=r'\w+'
s='first 1 second 2 third 3 —— _'
o=re.findall(pattern,s)
print(o)
# 结果
# ['first', '1', 'second', '2', 'third', '3', '_']
re.finditer
re.finditer 函数 和 findall 类似,在字符串中找到正则表达式所匹配的所有子串,并把它们作为一个迭代器返回。
pattern=r'\w+'
s='first 1 second 2 third 3 —— _'
o=re.finditer(pattern,s)
print(o)
for i in o:
print(i)
# <callable_iterator object at 0x00000261F2F84E80>
# <re.Match object; span=(0, 5), match='first'>
# <re.Match object; span=(6, 7), match='1'>
# <re.Match object; span=(8, 14), match='second'>
# <re.Match object; span=(15, 16), match='2'>
# <re.Match object; span=(17, 22), match='third'>
# <re.Match object; span=(23, 24), match='3'>
# <re.Match object; span=(28, 29), match='_'>
splite函数
re.split(pattern, string[, maxsplit=0, flags=0])
| 参数 | 描述 |
|---|---|
| pattern | 匹配的正则表达式 |
| string | 要匹配的字符串。 |
| maxsplit | 分隔次数, maxsplit=1分隔一次,默认为0,不限制次数。 |
| flags | 标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。 |
import re
s='first 11 second 22 third 33' #按数字切分
print(re.split(r'\d+',s)) # maxsplit 参数限定分隔的次数,这里限定为 1,也就是只分隔一次
print(re.split(r'\d+',s,1))
# 结果:
# ['first ', ' second ', ' third ', '']
# ['first ', ' second 22 third 33']
re.sub 和 re.subn搜索与替换
sub 函数和 subn 函数用于实现搜索和替换功能。这两个函数的功能几乎完全相同,都是将某个字符串中所有匹配正则表达式的部分替换成其他字符串。
sub 函数返回替换后的结果,
subn 函数返回一个元组,元组的第 1 个元素是替换后的结果,第 2 个元素是替换的总数。
语法为:
re.sub(pattern, repl, string, count=0, flags=0)
| 参数 | 描述 |
|---|---|
| pattern | 匹配的正则表达式 |
| repl | 替换的字符串,也可为一个函数 |
| string | 要被查找替换的原始字符串。 |
| count | 模式匹配后替换的最大次数,默认0表示替换所有的匹配 |
import re
phone = "哎呀喂 2004-959-559 # 这是一个国外电话号码" # 删除字符串中的 Python 注释
# 第一个参数是中文的范围
rex = '[\u4e00-\u9fa5]|#'
# sub返回替换结果 0 代表无穷个
str = re.sub(rex,"",phone,0)
print(str)
# 使用subn
rex_compiled = re.compile(r'[\u4e00-\u9fa5]|#')
result = rex_compiled.subn("",phone,0)
# 替换结果
print(result[0])
# 替换个数
print(result[1])
贪婪模式和非贪婪模式
Python里数量词默认是贪婪的,总是尝试匹配尽可能多的字符,非贪婪则相反,总是尝试匹配尽可能少的字符。
在"*","?"+";"{m,n}"后面加上?,使贪婪变成非贪婪。
import re
test = 'acbacbabbb'
# 非贪婪模式
rex = re.compile('a.*?b')
print(rex.search(test)) # <re.Match object; span=(0, 3), match='acb'>
#贪婪模式
rex = re.compile('a.*b')
print(rex.search(test))# <re.Match object; span=(0, 10), match='acbacbabbb'>
浙公网安备 33010602011771号