目录
一、正则表达式
(1)什么是正则表达式
(2)它的结构及使用
示例:
1.字符 . (←这里有个小点哦)
2.字符 |
3.字符 [ ]
4.字符^
5.字符\d
(3)补充:表示数量
示例:
1.字符+
2.字符*
3.字符?
4.字符{n}
二、贪婪模式与非贪婪模式
(1)贪婪模式
(2)非贪婪模式
三、捕获组
四、re模块
(1)re库函数一览
(2)具体用法示例
1.re.findall(pattern,string,flags)
2.re.compile(pattern,[flags])
3.re.match(pattern,string,flags = 0)
4.re.search(pattern,string,flags = 0)
5.group 和 groups 函数
6.re.sub(pattern,replace,string,count=0,flags=0)
7.re.split(pattern,string,maxsplit = 0,flags = 0)
本节内容较长,有一定难度,还请耐心观看~~~
一、正则表达式
(1)什么是正则表达式
标准解释:正则表达式,又称规则表达式,它是一种文本模式,同时也是计算机科学的一个概 念,其中包括普通字符(例如,a 到 z 之间的字母)和特殊字符(称为"元字符 ")。
正则表达式使用单个字符串来描述、匹配一系列匹配某个句法规则的字符 串,通常被用来检索、替换那些符合某个模式(规则)的文本。
简单来说,它就像一种“搜索语言”,它允许你通过特定的符号搜索你想要的文本。
比如,你面前有一大堆文本文字,这时你就可以通过代码搜索找出你想要的有价值的文本
(2)它的结构及使用
正则表达式由两部分构成:一个是普通字符,一个是特殊字符。
所谓普通字符,就是a,b,c……z和A,B,C……Z这些英文字母、数字0到9、标点符号。
所谓特殊字符,又叫元字符,它包括:
(看不懂,别急,直接后面看示例)
字符 | 作用 |
. | 匹配除\n 之外的任何单个字符。 |
| | 匹配两侧任意表达式 |
[ ] | 匹配里面的字符 |
^ | 匹配以^之后字符开头的字符串 |
[^] | [^abc]表示非a或非b或 非c的单个字符 |
\d | 匹配一个数字字符,等价于[0-9] |
\D | 匹配一个非数字字符,等价于[^0-9] |
\s | 匹配任何空白字符,包括空格、制表符、换页符等等。 |
\S | 匹配任何非空白字符。等价于[^\f\n\r\t\v] |
\w | 匹配任何单词字符,包括下划线。等价于“[A-Z和a-z和0-9_]” |
\W | 匹配任何非单词字符。等价于“[^A-Za-z0-9_]” |
\f | 匹配一个换页符 |
\n | 匹配一个换行符 |
\r | 匹配一个回车符 |
示例:
前言:正则表达式要用到re模块哦~~~
1.字符 . (←这里有个小点哦)
它的作用是,匹配除\n 之外的任何单个字符。
这里用到了re模块的findall(a,b)函数 ,作用是 在b中搜索字符串a,然后以列表类型返回符合的字符串
例如:
import re
a=re.findall('张.',"张三,李四,王五,张六七")
print(a)
我们可以看到,需要匹配的字符串是 张. 翻译过来就是,匹配 张+张后面一个单字符。
所以,系统输出:
['张三', '张六']
当然你要是想匹配张和后面俩字符,就可以改成 张.. (←俩点)
就变成:
import re
a=re.findall('张..',"张三,李四,王五,张六七")
print(a)
系统输出:
['张三,', '张六七']
2.字符 |
它的作用是,匹配两侧任意表达式,如果不存在,则不返回
比如:
import re
a=re.findall('cat|dog',"i have a cat and a dog")
print(a)
系统输出:
['cat', 'dog']
3.字符 [ ]
它的作用是,匹配里面的字符
比如:
import re
a=re.findall('[ab]',"abcd齐齐")
print(a)
系统输出:
['a', 'b']
当然如果 [ ] 里有\n之类的话,为防止将 \ 被误解为转义符,最好是前面加个r,如:r‘[ab]’
4.字符^
他的作用是,匹配以^之后字符开头的字符串
如下面代码:^hello就是匹配以hello开头的字符串
import re
a = re.findall('^hello', "hello world")
print(a)
系统输出:
['hello']
5.字符\d
它的作用是,匹配一个数字字符,等价于[0-9]
import re
a = re.findall(r'\d',"我的电话号码是110")
print(a)
输出:
['1', '1', '0']
注意,这里要用上了 r 防止 \ 被误解哦~~
相信通过这5个例子,你应该初步掌握了,那么再回过头看那个表格是不是清楚多了
(3)补充:表示数量
当然了,正则表达式不仅只有上面那些。
它的特殊符还包括以下这些:
(还是一样,看不懂直接看示例)
字符 | 作用 |
+ | 匹配前面的子表达式一次或多次。 |
* | 匹配前面的子表达式零次或多次。 |
? | 匹配前面的子表达式零次或一次。 |
{n} | n是一个非负整数,匹配确定的n次。 |
{n,} | n是一个非负整数,至少匹配n次。 |
{n,m} | m和n均为非负整数,其中n<=m。最少匹配n次且最多匹 配m次。 |
{,n} | n是一个非负整数,至多匹配n次。 |
示例:
1.字符+
匹配前面的子表达式一次或多次
比如下面代码,a+,就相当于将开头是a的全部找出来
import re
print(re.findall('a+',"abcadefaaghaaa"))
系统输出:
['a', 'a', 'aa', 'aaa']
当然,上面可能说的不太准确,准确的来说,是将一个以a为开头,一个或多个a为结尾的找出来,我们可以看下面这个例子,ab+来理解一下:
import re
print(re.findall('ab+',"abcadefabaghabbcaba"))
系统输出:
['ab', 'ab', 'abb', 'ab']
我们可以看到它将一个以a为开头,一个或多个b为结尾的字符找了出来,简单来说,
就是除了最后面的字符b可以是一个或者很多个,但你前面的a必须是一个。
我们再来看一个例子理解一下,如abc+
import re
print(re.findall('abc+',"abcadeabbcababcc"))
系统输出:
['abc', 'abcc']
这里就是将一个以ab为开头,一个或多个c为结尾的字符找出来。
当然,标准的解释并不是这样,这只是对匹配一次或多次的人话解释版本。
2.字符*
匹配前面的子表达式零次或多次
如果你能理解字符+,那么字符*也很好理解,比如下面代码:
import re
print(re.findall('ha*', "wo-hahaahh"))
系统输出:
['ha', 'haa', 'h', 'h']
我们用人话理解匹配零次或多次,就是将一个以h为开头,零个或多个a为结尾的找出来
3.字符?
匹配前面的子表达式零次或一次
如代码:
import re
print(re.findall('ha?',"wo-hahaahh"))
系统输出:
['ha', 'ha', 'h', 'h']
这里用人话理解匹配零次或一次,就是将一个以h为开头,零个或一个a为结尾的找出来
4.字符{n}
匹配确定的n次
我们经过理解,所谓的匹配几次就是,将一个以甲为开头,以几个乙为结尾的找出来
那么这里,也是一样的。比如我们匹配三次ab,那就是一个a开头,三个b为结尾的:
import re
print(re.findall('ab{3}',"ababbabbbabbbb"))
输出:
['abbb', 'abbb']
如果这个你能理解,相信{n,m}什么的,看看上面的表格的功能介绍,你也能理解了吧。
二、贪婪模式与非贪婪模式
所谓贪不贪婪啊,其实就是你要匹配多少个。
你想匹配的多了,那就是贪婪模式,想匹配少点,那就叫非贪婪模式喽~~
(1)贪婪模式
我们经过上面的学习,是不是已经发现计算机每次都默认匹配多次了,比如字符+和*之类。
对,所以啊,出现诸如:“{m,n}”、“{m,}”、“?”、“*”和“+”之类的,那都默认是贪婪模式。
我们在上面已经学习清楚了,就不再多赘述贪婪模式。
现在来将一个概念:回溯
标准解释:在匹配过程中,如果后面的部分无法匹配成功,贪婪模式会进行回溯, 即让出已经匹配成功的一部分字符,以便使整个表达式能够匹配成功。
有没有感觉很熟悉,这不就是我一直说的人话解释吗:将一个以甲为开头,以几个乙为结尾的找出来。
简单来说,就是我去匹配ab,在一串字符abbb中,字符+匹配,第一次匹配,我匹配到了ab,然后我想接着匹配,我想找a,但是没有啊,所以我就回溯,就是不要第一个已经匹配成功的字符a了,我就找b就行了,所以最后输出abbb
以上便是贪婪模式。
当然,如果关于回溯你没有太懂,没关系,这不重要,你只要记住我的人话版,一样能写代码。
(2)非贪婪模式
非贪婪模式与贪婪模式相反,它会在匹配成功的前提下,尽可能少地匹配字 符。
还是比如,我在一串字符abbb中用字符+去匹配ab,在非贪婪模式下,我只会得到ab
这还是很好理解的。
非贪婪模式的表示:在字符后面加一个?
比如ab+?、ab*?、ab??、ab{3,5}?
我们来看一个代码,加深理解:
import re
print(re.findall('ab*?',"abbbbbbbbcd"))
print(re.findall('ab+?',"abbbbbbbbcd"))
print(re.findall('ab??',"abbbbbbbbcd"))
print(re.findall('ab{3,5}?',"abbbbbbbbcd")) #这里的5碰上?就相当于没用了
输出:
['a']
['ab']
['a']
['abbb']
三、捕获组
先说说什么是捕获组?
捕获组就是一个可以让你从一个字符串中提取出多个有用的子字符串的东西
简单来说呢,就是把我们找出来的字符串分成一个一个组。
捕获组,就是我们用( )括起来的东西,这样就被提取为了一个单独的“组”
多说无用,来看一个代码:
import re
print(re.findall(r'\w+:\d+',"Alex:1994,Sunny:1996"))
print(re.findall(r'(\w+):\d+',"Alex:1994,Sunny:1996"))
print(re.findall(r'(\w+):(\d+)',"Alex:1994,Sunny:1996"))
依次输出:
['Alex:1994', 'Sunny:1996']
['Alex', 'Sunny']
[('Alex', '1994'), ('Sunny', '1996')]
解释:
第一行:\w+:\d+意思是查找格式为 字符:数字 的字符
第二行:(\w+):\d+ 加上括号后,就将\w+捕获成一个组了,此时就只会输出被捕获的字符。
第三行:(\w+):(\d+)都加上括号,就捕获了两个组,所以只输出捕获的两个组,我们可以看到相必第一个,此时没有了冒号
当然,以上只是捕获组的简单用法,稍后在re模块中,我们再详细介绍它。
四、re模块
调用方法:import re
(1)re库函数一览
(2)具体用法示例
1.re.findall(pattern,string,flags)
解释:
pattern:正则表达式或要匹配的字符
string:一大串字符串内容
flags:一些参数,可以达成如忽略大小写进行匹配等的目的。
上文都是用这个函数的,这里不过多论述。
这里主要说说flags参数,它有如下几个参数:
使用时,可写成诸如 re.findall(r'ab*',"abbbbbbbbcd",re.I)
2.re.compile(pattern,[flags])
它主要是可以将正则表达式对象复用,避免了每次调用时都重新编译正则表达式,提高了效率。
import re
# 编译正则表达式
pattern = re.compile(r'\d+')
# 使用编译后的正则表达式对象进行匹配
result = pattern.findall('There are 123 apples and 45 bananas.')
print(result)
输出:
['123', '45']
3.re.match(pattern,string,flags = 0)
解释:
pattern:正则表达式或要匹配的字符
string:一大串字符串内容
flags:同1中的参数
这里它其实和re.findall的用法是一样的,唯一不同的是:
re.match()
只检查字符串的起始部分,如果起始部分与正则表达式匹配,返回一个匹配对象。re.findall()
会扫描整个字符串,返回所有符合正则表达式的部分,返回一个包含所有匹配项的列表。
比如:
result = re.match(r'\d+','apples 123')
print(result) # 输出 None
tips:哪是起始部分,看的是空格哦
4.re.search(pattern,string,flags = 0)
参数原理同re.match和re.findall一样。
而re.search与他们不同的是:扫描整个字符串,查找第一个匹配的子串。如果找到匹配,返回一个匹配对象;如果没有匹配,返回 None
5.group 和 groups 函数
先说group()
它用于返回匹配到的整个字符串。
参数默认为 0,表示获取整个字符内容。
参数为1,则表示获取第一个捕获组 (没错,它又出现了,上文三中有解释哦)
参数为2,则表示获取第二个捕获组
……
参数为n,则表示获取第n个捕获组
当然,如果获取不存在的捕获组,就会报错。
比如,我们先设定好如下代码:
import re
pattern =r"(\w+)\s(\w+)"
string = "Hello World"
我们可以看到,上面的代码中有两个捕获组,然后输入下面的代码:
print(re.search(pattern, string).group())
print(re.search(pattern, string).group(1))
print(re.search(pattern, string).group(2))
输出:
Hello World #默认参数为0,输出整个匹配到的字符
Hello #参数为1,输出1个捕获组
World #参数为2,输出2个捕获组
再说groups( )
它跟group()不同的是,groups()不管参数是几,都将捕获组全部给你以元组形式返回来
如果没有捕获组,group()会报错,而groups()会返回一个空元组。
比如,我们继续输入代码:
import re
pattern =r"(\w+)\s(\w+)"
string = "Hello World"
print(re.search(pattern, string).groups())
print(re.search(pattern, string).groups(2))
输出:
('Hello', 'World')
('Hello', 'World')
6.re.sub(pattern,replace,string,count=0,flags=0)
功能:使用一个字符串替换正则表达式匹配到的内容
pattern:正则表达式或要匹配的字符
replace:替换匹配字符串的字符串
string:一大串字符串内容
count:匹配的最大替换次数
flags:同前文解释
简单来说,就是替换字符用的,直接看代码:
import re
print(re.sub(':','-',"Alex:1994,Sunny:1996"))
print(re.sub(':','-',"Alex:1994,Sunny:1996",1))
输出:
Alex-1994,Sunny-1996
Alex-1994,Sunny:1996
解释:
第一个print里,意思是将“:”替换成“-”然后输出
第二个print里,因为后面有一个1,所以意思是将一个“:”替换成“-”然后输出
7.re.split(pattern,string,maxsplit = 0,flags = 0)
功能:按正则表达式匹配内容,切割目标字符串
pattern:正则表达式或要匹配的字符
string:一大串字符串内容
maxsplit:最大分割数,剩余部分作为最后一个元素输出
flags:同前文
比如下面代码:
import re
print(re.split(r'\d{6}', 'BIT100081 TSU100084'))
print(re.split(r'\d{6}', 'BIT100081 TSU100084',1))
输出:
['BIT', ' TSU', ' ']
['BIT', ' TSU100084']
解释:
第一个print:意思是,匹配6次数字并删除掉
第二个print:意思是,仅在第一个组里,匹配6次数字并删掉
tips:各位可能发现,输出的最后多了一个‘ ’,这是为啥呢?
答:这是因为匹配到数字后,
re.split()
会将匹配部分删除,并在其位置插入空字符串。如果字符串的结尾部分没有其他字符,那么在re.split()
后会产生一个额外的空字符串。
致此,正则表达式讲解完毕~!