目录
1.正则表达式简介
2. 正则表达式语法:
2-1 普通字符:
2-2 特殊字符:
2-3 数量限定
2-4 指定匹配位置:
2-5 贪婪非贪婪模式
2-6 分组匹配
3.Python正则表达式的使用
3-1 正则表达式对象
3-2 正则表达式对象的方法
3-2-1 Pattern.search(string,pos,endpos)
3-2-2 Pattern.match(string,pos,endpos)
3-2-3 Pattern.fullmatch(string,pos,endpos)
3-2-4 Pattern.findall(string,pos,endpos)
3-2-5 pattern.split(string, maxsplit=0)
3-2-6 pattern.sub(repl, string, count=0, flags=0)
3-3 正则表达式对象属性:
3-3-1 pattern.flags
3-4 re模块自带的函数
-》regular expression简单翻译为”有规则的表达式“,即该表达式是一条规则,正则表达式引擎能够根据这条规则,在字符串中寻找所有符合规则的部分
-》正则表达式是一个特殊的字符序列,方便检查一个字符串是否与某种模式匹配
-》Python 自1.5版本起增加了re 模块(标准库),Python通过re模块提供对正则表达式的支持
#在字符串中查找匹配的子串 (普通字符子串)
import re
print(re.findall("hello","hahwiehellowordhahah")) #['hello'], 查找子串'hello'
print(re.findall("hello","hahwiewordhahhah")) #[]
print(re.findall("hello","hahwiehellowordhahhelloah")) #['hello', 'hello']
正则表达式使用反斜线字符 \ 作为Escape(转义)符,让特殊字符失去含义
.匹配除换行符以外的任何单个字符
import re
print(re.findall("hellowo.d","hahwiehellowordhahah")) #['helloword']
\d匹配非数字,相当于[0-9]
import re
print(re.findall("\d","aahhhjjj211hh1276833a")) #['2', '1', '1', '1', '2', '7', '6', '8', '3', '3'],找出数字
print(re.findall("\d\d","aahhhjjj211hh1276833a")) #['21', '12', '76', '83']
\D匹配数字,相当于[^0-9]
import re
print(re.findall("\D","aahhhjjj211hh1276833a")) #['a', 'a', 'h', 'h', 'h', 'j', 'j', 'j', 'h', 'h', 'a']
print(re.findall("\D\D","aahhhjjj211hh1276833a")) #['aa', 'hh', 'hj', 'jj', 'hh']
print(re.findall("\D\d","aahhhjjj211hh1276833a")) #['j2', 'h1']
[...] 匹配[]中的任意单个字符,[abc]匹配a或b或c
import re
print(re.findall("hel[abcd]oword","hahwiehelaowordhahah")) #['helaoword']
[^...]匹配不在[]中的单个字符
import re
print(re.findall("hel[^abc]oword","hahwiehelbowordhahah")) #[]
print(re.findall("hel[^abc]oword","hahwieheldowordhahah")) #['heldoword']
[-] 匹配指定字符范围中的单个字符
print(re.findall("hel[a-c]oword","hahwiehelbowordhahah")) #['helboword'] , 匹配a,b,c字符
注意:
如果要匹配反斜杠,需要输入正则表达式\\ (两个反斜杠)
如果要匹配两个反斜杠,需要输入正则表达式\\\\ (四个反斜杠)
在以 'r' 为前缀的字符串文字中不以任何特殊方式处理反斜杠
字符 | 描述 |
X? | 匹配前面的子表达式X零次或一次,要匹配 ? 字符使用 \? |
X* | 匹配前面的子表达式X零次或多次,要匹配 * 字符使用 \* |
X+ | 匹配前面的子表达式X一次或多次,要匹配 + 字符使用 \+ |
X{n} | 匹配前面的子表达式X n次 |
X{n,} | 匹配前面的子表达式X最少n次 |
X{n,m} | 匹配前面的子表达式X最少n次,不超过m次 |
*控制前面的字符,匹配0到多个
import re
print(re.findall("hel*oword","hahwieheowordhahah")) #['heoword'], 匹配到0个l
print(re.findall("hel*oword","hahwiehelowordhahah")) #['heloword'], 匹配到1个l
print(re.findall("hel*oword","hahwiehellowordhahah")) #['helloword'], 匹配到两个l
+控制前面的字符,匹配1到多个
import re
print(re.findall("hel+oword","hahwieheowordhahah")) #[], 0个l匹配失败
print(re.findall("hel+oword","hahwiehelowordhahah")) #['heloword'], 匹配到1个l
print(re.findall("hel+oword","hahwiehellowordhahah")) #['helloword'], 匹配到两个l
?匹配前面的字符0到1个,有多个只匹配1个
import re
print(re.findall("hel?oword","hahwieheowordhahah")) #['heoword'], 匹配到0个l
print(re.findall("hel?oword","hahwiehelowordhahah")) #['heloword'], 匹配到1个l
print(re.findall("hel?oword","hahwiehellowordhahah")) #[],有两个l,匹配失败
print(re.findall("hel?","hahwiehellowordhahah")) #['hel'],存在两个l,只匹配1个l
{}控制前面字符的匹配个数
import re
print(re.findall("hel{3}oword","hahwiehelllowordhahah")) #['hellloword'] ,匹配到3个l
print(re.findall("hel{3}oword","hahwiehellowordhahah")) #[] ,只有2个l,匹配失败
print(re.findall("hel{3}oword","hahwiehellllowordhahah")) #[],有4个l,匹配失败
print(re.findall("hel{3}","hahwiehellllowordhahah")) #['helll'] ,结尾取3个l
print(re.findall("hel{3,5}","hahwiehellllowordhahah")) #['hellll'], 结尾取3-5个l,此处匹配到4个l
print(re.findall("hel{3,5}","hahwiehelllllllllowordhahah"))
#['helllll'], 结尾取3-5个l,此处匹配到5个l
边界字符只用于描述边界信息,不用于字符的匹配
^号匹配字符串或者行的开头
import re
print(re.findall("^helloword","hahwiehellowordhahah"))
#输出[] ,开头不是helloword,匹配结果为空
print(re.findall("^hahwie","hahwiehellowordhahah"))
#输出['hahwie'] ,字符串开头部分匹配成功
$号匹配字符串或者行的结尾
import re
print(re.findall("helloword$","hahwiehellowordhahah"))
#输出[] , 结尾不是helloword,匹配结果为空
print(re.findall("dhahah$","hahwiehellowordhahah"))
#输出['dhahah'] ,字符串结尾部分匹配成功
#\b匹配单词的边界
print(re.findall(r"\bhello","hello hahah"))
#输出['hello'] ,单词边界匹配到hello
#\B匹配非单词的边界
print(re.findall(r"\Bhello","hahellohah"))
#输出['hello'] ,单词非边界匹配到hello
-》 *, + , ?, {m,n} 限定符都是贪婪的; 它们匹配尽可能多的文本,比如<.*>与 'b
-》通过在限定符后添加?将以非贪婪模式进行匹配,匹配到尽可能到的字符,比如<.*?>将匹配到
*?非贪婪模式(匹配0个则符合条件)
import re
print(re.findall("hel*","hahwiehelllllllllll")) #['helllllllllll'],*是贪婪模式,会尽可能多匹配字符
print(re.findall("hel*?","hahwiehelllllllllll")) #['he'],非贪婪模式,最少匹配0个字符
+?非贪婪模式(匹配1个则符合条件)
import re
print(re.findall("hel+","hahwiehellllllwordhahah")) #['hellllll'] ,*是贪婪模式会尽可能多匹配字符
print(re.findall("hel+?","hahwiehellllllwordhahah")) #['hel'] ,非贪婪模式,最少匹配1个字符
?? 非贪婪模式(匹配0个则符合条件)
import re
print(re.findall("hel?","hahwiehelllllowordhahah")) #['hel'], ?贪婪模式匹配到1个l
print(re.findall("hel??","hahwiehelllllowordhahah")) #['he'],??非贪婪模式,匹配0个字符
{m,n}?非贪婪模式(匹配m个字符则符合条件)
import re
print(re.findall("hel{3,5}","hahwiehelllllllllowordhahah"))#['helllll'], 贪婪模式匹配最多5个字符
print(re.findall("hel{3,5}?","hahwiehelllllllllowordhahah"))#['helll'],非贪婪模式匹配最少3个字符
正则表达式中使用()可以进行分组匹配,结果对象的group系列方法可以分别获取分组结果
pattern = re.compile(pattern=r'(\w)(\w)(\w)')
searchResult = pattern.search(string='122dfdf1212sdsd8787fdfd')
print(searchResult) #
, 生成Match结果对象 print(searchResult.groups()) #('1', '2', '2') , groups返回所有分组结果
print(searchResult.group(0)) #122, 获取整个匹配结果
print(searchResult.group(1)) #1 ,获取第1个括号对应的匹配结果
print(searchResult.group(2)) #2,获取第2个括号对应的匹配结果
print(searchResult.group(3)) #2,获取第3个括号对应的匹配结果
在写好一条规则后,比如r'hello*word', 在python中还只是一个字符串,,需要将这个字符串编译一下,成为表达式对象
compile 函数用于编译正则表达式,生成一个正则表达式( Pattern )对象,供 match() 和 search() 这两个函数使用
compile(pattern, flags=0)
pattern: 字符串形式的正则表达式
flags: 正则表达式修饰符,匹配模式,比如忽略大小写,多行模式
flags:
正则表达式可以包含一些可选标志修饰符来控制匹配的模式
多个标志可以通过按位 OR(|) 它们来指定。如 re.I | re.M 被设置成 I 和 M 标志
1、re.IGNORECASE (re.I) 忽略大小写
2、re.ASCII (re.A) 只匹配ASCII
3、re.MULTILINE (re.M) 多行模式
4、re.DOTALL (re.S) .号可以匹配包括换行符在内的所有字符
5、re.VERBOSE (re.X) 可识别注释信息,自动忽略注释信息
6、re.LOCALE (re.L)做本地化识别(locale-aware)匹配
7、re.UNICODE (re.U)表示特殊字符集 \w, \W, \b, \B, \d, \D, \s, \S 依赖于 Unicode 字符属性
import re
pattern = re.compile(pattern='hello*word',flags=0) #生成正则表达式对象
result = pattern.match("helloooword") #match函数生成re.Match object对象
print(result) #输出
#等价于
result = re.match(pattern='hello*word',string='helloooword',flags=0)
print(result) #输出
以上两种实现方式
方式1:re.compile先生成正则表达式对象,再调用match方法
方式2:直接调用re.match方法 (内部其实也是先编译成正则表达式对象)
正则表达式对象可以被重用,因此更推荐方式1
search方法扫描整个字符串,查找第一个能匹配上pattern的部分,并返回相应的匹配对象,匹配失败则返回None
Pattern.search(string,pos,endpos)
1、string: 必填参数,表示待查找的字符串
2、pos: 可选参数,从指定的pos索引位置开始搜索,默认为0
3、endpos:可选参数,指定截至位置
pattern = re.compile(pattern='hello*word',flags=0)
searchResult = pattern.search('hahwiehelloooooowordhahah')
print(searchResult) #输出
searchResult = pattern.search('hahwiehelloooooowordhahah',6)
print(searchResult) #输出
searchResult = pattern.search('hahwiehelloooooowordhahah',7)
print(searchResult) #输出None
searchResult = pattern.search('hahwiehelloooooowordhahah',endpos=20)
print(searchResult) #输出
searchResult = pattern.search('hahwiehelloooooowordhahah',endpos=19)
print(searchResult) #输出None,只有从pos到endpos - 1的字符才会被搜索到
match方法从字符串起始位置进行匹配,匹配成功返回匹配对象,不匹配返回None
Pattern.match(string,pos,endpos)
1、string: 必填参数,表示待查找的字符串
2、pos: 可选参数,从指定的pos索引位置开始搜索,默认为0
3、endpos:可选参数,指定截至位置
pattern = re.compile(pattern='hello*word',flags=0)
searchResult = pattern.match('helloooooowordhahah')
print(searchResult) #输出
searchResult = pattern.match('hahwiehelloooooowordhahah')
print(searchResult) #输出None
searchResult = pattern.match('hahwiehelloooooowordhahah',pos=6)
print(searchResult) #输出
指定pos开始位置,则将从开始位置进行匹配
fullmatch方法匹配整个字符串,整个字符串和pattern匹配上才算是匹配成功,返回匹配对象,不匹配返回None
Pattern.fullmatch(string,pos,endpos)
1、string: 必填参数,表示待查找的字符串
2、pos: 可选参数,从指定的pos索引位置开始搜索,默认为0
3、endpos:可选参数,指定截至位置
pattern = re.compile(pattern='hello*word',flags=0)
searchResult = pattern.fullmatch('helloooooowordhahah')
print(searchResult) #输出None
searchResult = pattern.fullmatch('hahwiehelloooooowordhahah',pos=6,endpos=20)
print(searchResult) #输出
设定pos,endpos之后,则从pos-endpos位置进行匹配
findall找到正则表达式所匹配的所有子串,并返回一个列表,如果有多个匹配模式,则返回元组列表,如果没有找到匹配的,则返回空列表
Pattern.findall(string,pos,endpos)
1、string: 必填参数,表示待查找的字符串
2、pos: 可选参数,从指定的pos索引位置开始搜索,默认为0
3、endpos:可选参数,指定字符串的结束位置,默认为字符串的长度
pattern = re.compile(pattern=r'\d+')
searchResult = pattern.findall('hel3loooo22oowor232dhah3232ah')
print(searchResult) #输出['3', '22', '232', '3232']
split 方法按照能够匹配的子串将字符串分割后返回列表
pattern.split(string, maxsplit=0)
string: 必填参数,表示待匹配的字符串
maxsplit: 分隔次数,maxsplit=1 表示分隔一次,默认为 0,不限制次数
pattern = re.compile(pattern='\d',flags=0)
splitResult = pattern.split('tssj4jfdjkfj88dnfksdkf7sdjfh6')
print(splitResult) #输出['tssj', 'jfdjkfj', '', 'dnfksdkf', 'sdjfh', '']
pattern = re.compile(pattern='(\d)',flags=0)
splitResult = pattern.split('tssj4jfdjkfj88dnfksdkf7sdjfh6')
print(splitResult) #输出['tssj', '4', 'jfdjkfj', '8', '', '8', 'dnfksdkf', '7', 'sdjfh', '6', '']
#在表达式中使用捕获括号,则表达式中所有组的文本也会作为结果列表的一部分返回
pattern = re.compile(pattern='\d',flags=0)
splitResult = pattern.split('tssj4jfdjkfj88dnfksdkf7sdjfh6',maxsplit=1)
print(splitResult) #输出['tssj', 'jfdjkfj88dnfksdkf7sdjfh6']
maxsplit=1表示进行1次分割, 字符串的其余部分作为列表的最后一个元素返回
sub方法找到匹配的子串,替换成其他字符串
pattern.sub(repl, string, count=0, flags=0)
repl : 替换的字符串,可以是函数
string : 要被查找替换的原始字符串
count : 模式匹配后替换的最大次数,默认 0 表示替换所有的匹配
pattern = re.compile(pattern=r'\d+')
subResult = pattern.sub('aaa','hel3loooo22oowor232dhah3232ah')
print(subResult) #输出helaaalooooaaaooworaaadhahaaaah 匹配到数字,然后替换成aaa
def func(n):
return str(int(n.group())*3)
subResult = pattern.sub(func,'hel3loooo22oowor232dhah3232ah')
print(subResult) #输出hel9loooo66oowor696dhah9696ah,将匹配到的数字全部乘以3
#repl可以是一个函数,将对匹配到的内容进行更复杂的处理
传给func的是匹配对象列表,该对象包装了真正匹配到的数字
如'3','22','232','3233',所以使用了一个 n.group()来提取数字
正则表达式可以包含一些可选标志修饰符来控制匹配的模式
多个标志可以通过按位 OR(|) 它们来指定。如 re.I | re.M 被设置成 I 和 M 标志
1、re.IGNORECASE (re.I) 忽略大小写
2、re.ASCII (re.A) 只匹配ASCII
3、re.MULTILINE (re.M) 多行模式
4、re.DOTALL (re.S) .号可以匹配包括换行符在内的所有字符
5、re.VERBOSE (re.X) 可识别注释信息,自动忽略注释信息
6、re.LOCALE (re.L)做本地化识别(locale-aware)匹配
7、re.UNICODE (re.U)表示特殊字符集 \w, \W, \b, \B, \d, \D, \s, \S 依赖于 Unicode 字符属性
(1) re.IGNORECASE
语法: re.IGNORECASE 或简写为 re.I
忽略大小写匹配
pattern = re.compile(pattern=r'aaa')
subResult = pattern.findall('AAAaaa')
print(subResult) #输出['aaa']
pattern = re.compile(pattern=r'aaa',flags=re.IGNORECASE)
subResult = pattern.findall('AAAaaa')
print(subResult) #输出['AAA', 'aaa'] ,设置忽略大小写模式后,可以匹配到AAA
(2) re.ASCII
语法:re.ASCII 或简写为 re.A
ASCII表示ASCII码,让 \w, \W, \b, \B, \d, \D, \s 和 \S 只匹配ASCII,不匹配Unicode
pattern = re.compile(pattern=r'\w*')
subResult = pattern.findall('哈喽哈ad哈sjdfs')
print(subResult) #输出['哈喽哈ad哈sjdfs', '']
pattern = re.compile(pattern=r'\w*',flags=re.ASCII)
subResult = pattern.findall('哈喽哈ad哈sjdfs')
print(subResult) #输出['', '', '', 'ad', '', 'sjdfs', ''] , 只匹配到ASCII,中文部分匹配不到
(3) re.MULTILINE
语法: re.MULTILINE 或简写为 re.M
多行模式,支持换行符特性
正则表达式中
^
表示匹配行的开头,默认模式下它只能匹配字符串的开头;而在多行模式下,它还可以匹配 换行符\n
后面的字符正则语法中
^
匹配行开头、\A
匹配字符串开头,单行模式下效果一致,多行模式下\A
不能识别\n
(4) re.DOTALL
语法: re.DOTALL 或简写为 re.S
DOT表示.号,ALL表示所有,表示.号可以匹配所有字符,包括换行符\n (默认模式下是不能匹配行符\n的)
(5) re.VERBOSE
语法: re.VERBOSE 或简写为 re.X
作用: 详细模式,可以在正则表达式中加注解,可以识别正则表达式中的注释信息并且自动忽略
(6) re.LOCALE
语法: re.LOCALE 或简写为 re.L
做本地化识别(locale-aware)匹配
(7) re.UNICODE
语法: re.UNICODE 或简写为 re.U
作用: 与 ASCII 模式类似,匹配unicode编码支持的字符
以上使用正则表达式需要两个步骤,首先编译出正则表达式对象pattern,然后调用pattern的search,match等函数进行匹配, re模块也直接提供了search,match等快捷操作, 我们不需要先编译pattern
1、re.search(pattern, string, flags=0)
2、re.match(pattern, string, flags=0)
3、re.fullmatch(pattern, string, flags=0)
4、re.findall(pattern, string, flags=0)
5、re.split(pattern, string, maxsplit=0, flags=0)
6、re.sub(pattern, repl, string, count=0, flags=0)
实际上以上方法背后也是先用第一个参数编译成正则表达式对象然后让这个对象调用pattern的方法
使用上除了第一个参数是pattern,其他都和pattern的方法一样
searchResult = re.search(pattern='hello*word',string='hahwiehelloooooowordhahah')
print(searchResult) #输出