正则表达式
一、概述
1、正则表达式Regular Expression
一种文本模式,描述在搜索文本时要匹配的一个或多个字符串
2、典型应用场景
数据验证
文本扫描
文本提取
文本替换
文本分割
3、语法
4、匹配
单字,预定义元字符
. 表示除\n外的所有字符
\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_]
4.2、批量备选
| yes|no
4.3、量词 (字符、元字符,字符集如何重复)
? 0或1次
* 0或多次
+ 1或多次
特定
{3,5} 范围次数
{n} n次
{n,} 至少n次
{,n} 最多n次
4.4、贪婪与非贪婪
贪婪(默认) :尽量匹配最大范围结果
非贪婪:尽量匹配最小的范围结果
方法 :量词后追加?
例:
??
*?
+?
4.5、边界匹配
^ 表示行首
$ 表示行尾
\b 表示单词边界
\B 表示非单词边界
\A 表示输入开头
\Z 表示输入结尾
注:或因上下文差异有不同表现
二、Python 正则
模块
import re
1、RegexObject 正则对象
模式对象,表现编译后的正则表达式(编译为字节码并缓存)
编译
re.compile(r’模式’)
.findall()
查找所有非重叠匹配项
返回list
.match(string[,pos[,endpos]])
匹配,起始位置
返回 MatchObject
.search(string[,[pos[,endpos]]])
任意位置搜索
返回 MatchObject
.finditer()
查找所有匹配项
返回包含MatchObject元素的迭代器
import re
text = "Tom is 8 years old, Mike is 25 years old."
#先编译放到变量里,有利于重用
#匹配数字
pattern = re.compile('\d+')
pattern.findall(text) #['8', '25']
#临时应用
re.findall('\d+', text) #['8', '25']
#------findall()--------
s = "\\author:Tom"
pattern = re.compile('\\author')
#返回[]
pattern.findall(s)
pattern = re.compile('\\\\autor')
#返回['\\author']
pattern.findall(s)
pattern = re.compile(r'\\author')
#返回['\\author']
pattern,findall(s)
pattern = re.compile(r'\d+')
#返回['8', '23']
pattern.findall(text)
p_name = re.compile(r'[A-Z]\w+')
#返回['Tom', 'Mike']
p_name.findall(text)
#-----------match()-------------
pattern = re.compile(r'<html>')
text = '<html><head></head><body></body></html>'
#返回<re.Match object; span=(0, 6), match='<html>'>
pattern.match(text)
text2 = ' <html><head></head><body></body></html>'
#返回空
pattern.match(text2)
#从第二个字符开始
#返回<re.Match object; span=(1, 7), match='<html>'>
pattern.match(text2, 1)
#-----------search()--------------
#返回<re.Match object; span=(1, 7), match='<html>'>
pattern.search(text2)
text = "Tom is 8 years old, Mike is 25 years old."
p1 = re.compile(r'\d+')
p2 = re.compile(r'[A-Z]\w+')
#返回<re.Match object; span=(0, 3), match='Tom'>
p2.match(text)
#返回['8', '25']
p1.findall(text)
#-------------finditer()-------------
it = p1.finditer(text)
#输出<re.Match object; span=(7, 8), match='8'>
#输出<re.Match object; span=(28, 30), match='25'>
for m in it:
print(m)
MatchObject 匹配对象
表现被匹配的模式
.group()
1.参数为0或空返回整个匹配
2.有参时返回特定分组匹配细节
3.参数也可以是分组名称
.groups()
返回包含所有子分组的元组
.start()
返回特定分组的终止索引
.end()
返回特定分组的终止索引
.span()
返回特定分组的起止索引元组
.groupdict()
以字典表形式返回分组名及结果
import re
text = 'Tom is 8 years old, Jerry is 23 years old.'
pattern = re.compile(r'(\d+).*?(\d+)')
#<re.Match object; span=(7, 31), match='8 years old, Jerry is 23'>
m = pattern.search(text)
#'8 years old, Jerry is 23'
m.group()
#'8 years old, Jerry is 23'
m.group(0)
#'8'
m.group(1)
#'23'
m.group(2)
#7('8'的索引下标)
m.start(1)
#8('8'在哪终止)
m.end(1)
#29
m.start(2)
#31
m.end(2)
#返回('8', '23')
m.groups()
pattern = re.compile(r'(\w+) (\w+)')
text = 'Beautiful is better than ugly.'
#返回[('Beautiful, is'), ('better', 'than')]
pattern.findall(text)
it = pattern.finditer(text)
#返回Beautiful is
#返回better than
for m in it:
print(m.group())
Group 编组
场景
1.从匹配模式种提取信息
2.创建子正则以应用量词
3.限制备选项范围
4.重用正则模式中提取的内容
声明
1.(模式)
2.(?P<name>模式)
引用
1.匹配对象内 m.group('name')
2.模式内 (?P=name)
3.表现内 \g<name>
import re
#<re.Match object; span=(0, 5), match='ababc'>
re.search(r'(ab)+c', 'ababc')
#<re.Match object; span=(0, 6), match='Center'>
re.search(r'Cent(er|re)', 'Center')
#<re.Match object; span=(0, 6), match='Centre'>
re.search(r'Cent(er|re)', 'Centre')
#<re.Match object; span=(0, 11), match='hello hello'>
re.search(r'(\w+) \1', 'hello hello world')
text = 'Tom:98'
pattern = re.compile(r'(?P<name>\w+):(?P<score>\d+)')
m = pattern.search(text)
#'Tom:98'
m.group()
#'Tom'
m.group(1)
#'Tom'
m.group('name')
#'98'
m.group('score')
应用
字符串操作
.split(string, maxsplit=0)
分割字符串
分割
import re
text = 'Beautiful is better than ugly.\nExplicit is better than implicit.\nSimple is better than complex.'
p = re.compile(r'\n')
#返回['Beautiful is better than ugly.', 'Explicit is better than implicit.', 'Simple is better than complex.']
p.split(text)
返回#['Beautiful is better than ugly.', 'Explicit is better than implicit.', 'Simple is better than complex.']
re.split(r'\n', text)
#返回['Good', 'morning'],以非数字字母字符为分隔符
re.split(r'\W', 'Good morning')
#返回['Good', ' ', 'morning']
re.split(r'(\W)', 'Good morning')
#返回['Beautiful is better than ugly.', 'Explicit is better than implicit.\nSimple is better than complex.'],以一个\n为分隔符
re.split(r'\n', text, 1)
.sub(repl, string, count=0)
替换字符串
.subn(repl, string, count=0)
替换并返回替换数量
替换
import re
ords = 'ORD000\nORD001\nORD003'
#'ORD-\nORD-\nORD-'
re.sub(r'\d+', '-', ords)
text = 'Beautiful is *better* than ugly.'
#'Beautiful is +better+ than ugly.'
re.sub(r'\*(.*?)\*', '+\g<1>+', 'text')
#'Beautiful is +better+ than ugly.'
re.sub(r'\*(?P<name>.*?)\*', '+\g<name>+', text)
#'000-ORD\n001-ORD\n003-ORD'
re.sub(r'([A-Z]+)(\d+)', '\g<2>-\g<1>', ords)
#('000-ORD\n001-ORD\n003-ORD', 3),多加一个3 表示替换了3次
re.subn(r'([A-Z]+)(\d+)', '\g<2>-\g<1>', ords)
编译标记
改变正则的默认行为
re.I 忽略大小写
re.M 匹配多行
re.S 指定"." 匹配所有字符, 包括\n
...
import re
text = 'Python python PYTHON'
#['python']
re.findall(r'python', text)
#['Python', 'python', 'PYTHON']
re.findall(r'python', text, re.I)
text2 = '\n<html>'
#查找以<html>开头
#[]
re.findall(r'^<html>', text)
#['<html>']
re.findall(r'^<html>', text2, re.M)
#查找以数字开头后面任意
#返回[]
re.findall(r'\d(.)', '1\nasd')
#['\n']
re.findall(r'\d(.)', '1\nasd', re.S)
模块级别操作
re.purge() 清理正则缓存
re.escape() 逃逸字符
#查找^符号
#['']
re.findall(r'^', '^python^')
#['^', '^']
re.findall(r'\^', '^python^')
['^', '^']
re.findall(re.escape('^'), '^python^')