正则表达式
正则表达式是一个特殊的字符序列,它能帮助你方便的检查一个字符串是否与某种模式匹配。
概述
典型使用场景
1、数据验证;
2、文本扫描;
3、文本提取;
4、文本替换;
5、文本分割;
······
语法
正则表达式由字符串构成,其中分为两类:字面值、元字符。
字面值:字面值又包括普通字符,可直接表达原义,(如字母c)。还包括转义字符,需要在前面加“\”才能表达原义,(如^,$,|,?,*,+,(),[],{}等)。
匹配
1、单字,预定义元字符
(1). :除\n外所有的字符;
(2)\d :数字,等同于[0-9];
(3)\D :非数字;
(4)\s :空白字符,等同于\t\n\r\f\v;
(5)\S :非空白字符;
(6)\w :字母数字字符,等同于[a-zA-Z0-9];
(7)\W :非字母数字字符;
2、批量备选
用“|”表示,如取yes或no都可以,可表示为yes|no。
3、量词(字符、元字符、字符集如何重复)
(1)? :出现0次或1次;
(2)* :出现0次或多次;
(3)+ :出现1次或多次;
(4){n,m} :出现次数的范围;
(5){n} :出现n次;
(6){n,} :出现至少n次;
(7){,m} :出现最多m次。
4、贪婪与非贪婪
贪婪(默认):尽量匹配最大范围结果;
非贪婪:尽量匹配最小范围结果,方法是在量词后加“?”。
例:查找与之间的内容
默认贪婪模式
匹配结果
非贪婪模式
匹配结果
5、边界匹配
(1)^ :行首;
(2)$ :行尾;
(3)\b :单词边界;
(4)\B :非单词边界;
(5)\A :输入开头;
(6)\Z :输入结尾。
注:或因上下文差异有不同表现。
python中的正则表达式
RegexObject正则对象(re模块 )
re 模块使 Python 语言拥有全部的正则表达式功能。
例:从文本中查找年龄
不进行编译,直接查找
>>> import re
>>> text = "Tom is 8 years old. Mike is 25 years old."
>>> re.findall('\d+',text)
['8', '25']
编译为字节码后查找,适合多次使用
>>> import re
>>> text = "Tom is 8 years old. Mike is 25 years old."
>>> pattern = re.compile('\d+')
>>> pattern.findall(text)
['8', '25']
1、编译
re.compile(‘模式’)
通常在模式前加r,表示不需要转义:(r’模式’)
例:当\为需要查找的文本时,直接编译会将\当作转义符处理
>>> s = "\\author:Tom"
>>> pattern = re.compile('\\author')
>>> pattern.findall(s)
#运行结果
[]
可以通过在每个\前面再加一个\来处理,比较麻烦
>>> pattern = re.compile('\\\\author')
>>> pattern.findall(s)
#运行结果
['\\author']
也可以通过r表示不需要转义
>>> pattern = re.compile(r'\\author')
>>> pattern.findall(s)
#运行结果
['\\author']
2、查找
.findall()
查找所有非重叠匹配项,返回list。
>>> text = "Tom is 8 years old. Mike is 25 years old."
>>> p_age = re.compile(r'\d+')
>>> p_age.findall(text)
#运行结果
['8', '25']
>>> p_name = re.compile(r'[A-Z]\w+')
>>> p_name.findall(text)
#运行结果
['Tom', 'Mike']
3、.match函数
.match(string[,pos[,endpos]])
从字符串的起始位置匹配一个模式,返回MatchObject,如果起始位置匹配不成功的话,match()就返回none。
>>> import re
>>> text = '<html><head></head><body></body></html>'
>>> pattern = re.compile(r'<html>')
>>> pattern.match(text)
#运行结果
<re.Match object; span=(0, 6), match='<html>'>
>>> type(pattern.match(text))
#运行结果
re.Match
当起始位置为空格,匹配不成功
>>> text2 = ' <html><head></head><body></body></html>'
>>> pattern.match(text2)
#无运行结果
#可指定开始匹配的位置
>>> pattern.match(text2,1)
<re.Match object; span=(1, 7), match='<html>'>
4、.search函数
.search(string[,pos[,endpos]])
.search 可以任意位置搜索,返回MatchObject。
>>> text2 = ' <html><head></head><body></body></html>'
>>> pattern = re.compile(r'<html>')
>>> pattern.match(text2)
#无运行结果
>>> pattern.search(text2)
#运行结果
<re.Match object; span=(1, 7), match='<html>'>
5、.finditer()函数
查找所有非重叠匹配项,返回包含MatchObject元素的迭代器。
>>> text = "Tom is 8 years old. Mike is 25 years old."
>>> p1 = re.compile(r'\d+')
>>> p1.findall(text)
#运行结果,返回一个列表
['8', '25']
>>> p1.finditer(text)
#运行结果,返回一个包含MatchObject元素的迭代器
<callable_iterator at 0x27ee2792b48>
.finditer()函数返回结果可进行迭代
>>> it = p1.finditer(text)
>>> for m in it:
...: print(m)
...:
#运行结果
<re.Match object; span=(7, 8), match='8'>
<re.Match object; span=(28, 30), match='25'>
MatchObject匹配对象
主要功能为表现被匹配模式的详细信息。
例:利用re.search函数返回一个MatchObject对象
>>> import re
>>> text = "Tom is 8 years old. Mike is 25 years old."
>>> pattern = re.compile(r'(\d+).*?(\d+)') #括号代表分组,详见下节
>>> m = pattern.search(text)
>>> m
#运行结果
<re.Match object; span=(7, 30), match='8 years old. Mike is 25'>
1、.group()函数
.group()函数返回匹配的字符串
参数为0或空时返回整个匹配
>>> m.group()
#运行结果
'8 years old. Mike is 25'
>>> m.group(0)
#运行结果
'8 years old. Mike is 25'
通过指定参数可以返回特定分组匹配细节
>>> m.group(1)
#运行结果
'8'
>>> m.group(2)
#运行结果
'25'
2..groups()函数
.groups()函数返回包含所有子分组的元组
>>> m.groups()
#运行结果
('8', '25')
3、.start()函数
.start()函数返回特定分组的起始索引
>>> m.start(1)
#运行结果
7
>>> m.start(2)
#运行结果
28
4、.end()函数
.end()函数返回特定分组的终止索引
>>> m.end(1)
#运行结果
8
>>> m.end(2)
#运行结果
30
5..span()函数
.span()函数返回特定分组的起止索引元组
>>> m.span()
#运行结果
(7, 30)
Group编组
使用场景
1、从匹配模式中提取信息。
2、创建子正则以应用量词。
例:想要查找以c结尾,前面重复若干次ab的信息
>>> import re
>>> re.search(r'ab+c','ababc') #不分组,默认重复的是b
#运行结果
<re.Match object; span=(2, 5), match='abc'>
>>> re.search(r'(ab)+c','ababc') #分组后,则认为重复的是ab
#运行结果
<re.Match object; span=(0, 5), match='ababc'>
3、限制备选项范围。
例:center与centre写法都正确,需要在查找时两个词都能匹配上
不加分组时默认Center与re均为备选
>>> re.search(r'Center|re','Center')
#运行结果
<re.Match object; span=(0, 6), match='Center'>
>>> re.search(r'Center|re','Centre')
#运行结果
<re.Match object; span=(4, 6), match='re'>
加分组时默认er与re为备选
>>> re.search(r'Cent(er|re)','Center')
#运行结果
<re.Match object; span=(0, 6), match='Center'>
>>> re.search(r'Cent(er|re)','Centre')
#运行结果
<re.Match object; span=(0, 6), match='Centre'>
4、重用正则模式中提取的内容。
若在定义模式时想重用前面的编组,可用\加序号代替,序号从1开始
>>> re.search(r'(\w+)\1','hello hello world')
#运行结果
<re.Match object; span=(2, 4), match='ll'>
声明及引用
声明时直接用圆括号(模式)进行编组,当编组较多时,可以对其分别命名(?P模式)。
引用时可直接使用.group(序号),若已经命名,可使用.group(‘name’)。在模式内可用(?P=name),在表现内可用\g。
直接声明及引用
>>> import re
>>> text = "Tom:98"
>>> pattern = re.compile(r'(\w+):(\d+)') #直接分组,未命名
>>> m = pattern.search(text)
>>> m.group()
#运行结果
'Tom:98'
>>> m.group(1) #通过序号引用
#运行结果
'Tom'
声明时命名及引用
>>> pattern = re.compile(r'(?P<name>\w+):(?P<score>\d+)')
>>> m = pattern.search(text)
>>> m.group()
#运行结果
'Tom:98'
>>> m.group(1) #仍然可以通过序号引用
#运行结果
'Tom'
>>> m.group('name') #还可以通过名称引用
#运行结果
'Tom'
>>> m.group('score')
#运行结果
'98'
python正则的应用
字符串操作
1、分割字符串
.split(string, maxsplit=0)
>>> import re
>>> text = 'Beautiful is better than ugly.\nExplicit is better than implicit.\nSimple is better than complex.'
#1、先编译再切分
>>> p = re.compile(r'\n')
>>> p.split(text)
#运行结果
['Beautiful is better than ugly.',
'Explicit is better than implicit.',
'Simple is better than complex.']
#2、直接切分
>>> re.split(r'\n',text)
#运行结果
['Beautiful is better than ugly.',
'Explicit is better than implicit.',
'Simple is better than complex.']
若希望将分隔字符也打印出来,需要用括号将分隔字符括起来
>>> re.split(r'(\n)',text)
#运行结果
['Beautiful is better than ugly.',
'\n',
'Explicit is better than implicit.',
'\n',
'Simple is better than complex.']
可以指定按顺序切割出几部分
>>> re.split(r'\n',text,1)
#运行结果
['Beautiful is better than ugly.',
'Explicit is better than implicit.\nSimple is better than complex.']
2、替换字符串
.sub(repl, string, count=0)
例:将数字替换成-
>>> ords = 'ORD000\nORD001\nORD003'
>>> re.sub(r'\d+','-',ords)
#运行结果
'ORD-\nORD-\nORD-'
将单词两端的*替换成
>>> text = 'Beautiful is *better* than ugly.'
>>> re.sub(r'\*(.*?)\*','<strong></strong>',text) #这样会造成信息丢失
#运行结果
'Beautiful is <strong></strong> than ugly.'
>>> re.sub(r'\*(.*?)\*','<strong>\g<1></strong>',text) #可在表现中通过序号对分组重用
#运行结果
'Beautiful is <strong>better</strong> than ugly.'
>>> re.sub(r'\*(?P<html>.*?)\*','<strong>\g<html></strong>',text)#也可在表现中通过命名对分组重用
#运行结果
'Beautiful is <strong>better</strong> than ugly.'
该函数也可以改变字符串格式
>>> ords = 'ORD000\nORD001\nORD003'
>>> re.sub(r'([A-Z]+)(\d+)','\g<2>-\g<1>',ords)
#运行结果
'000-ORD\n001-ORD\n003-ORD'
3、替换并返回替换数量
.subn(repl, string, count=0)
>>> re.subn(r'([A-Z]+)(\d+)','\g<2>-\g<1>',ords)
#运行结果
('000-ORD\n001-ORD\n003-ORD', 3)
编译标记
改变正则的默认行为。
1、re.I 忽略大小写
>>> import re
>>> text = 'Python python PYTHON'
>>> re.findall(r'python',text)
#运行结果
['python']
>>> re.findall(r'python',text,re.I)
#运行结果
['Python', 'python', 'PYTHON']
2、re.M 匹配多行
>>> re.findall(r'^<html>','\n<html>')
#运行结果
[]
>>> re.findall(r'^<html>','\n<html>',re.M)
#运行结果
['<html>']
3、re.S 指定“.”匹配所有字符,包括“\n”
>>> re.findall(r'\d(.)','1\ne')
#运行结果
[]
>>> re.findall(r'\d(.)','1\ne',re.S)
#运行结果
['\n']
模块级别操作
1、清理正则缓存
re.purge()
2、逃逸字符
re.escape()
忽略字符原有意义
>>> re.findall(r'^','^python^')
#运行结果
['']
>>> re.findall(re.escape('^'),'^python^')
#运行结果
['^', '^']
未完待续!