Python入坑进阶第一步:模式匹配和正则表达式

一、模式匹配和正则表达式

1、使用正则表达式匹配文本模式

str ='2022-06-01是儿童节'

此时需要获取日期2022-06-01,该如何获取呢?答案:正则表达式!

>>> str ='2022-06-01是儿童节'
>>> #导入正则表达式函数所在的模块:re模块
>>> import re
>>> dateRegex1=re.compile('\\d\\d\\d\\d-\\d\\d-\\d\\d')
>>> date1=dateRegex1.search(str)
>>> print(date1.group())
2022-06-01
>>> #将字符串标记为原始字符串,就可以不包含转义字符!此处不理解,请翻看基础篇!
>>> dateRegex2=re.compile(r'\d\d\d\d-\d\d-\d\d')
>>> date2=dateRegex2.search(str)
>>> print(date2.group())
2022-06-01
>>> 

解析:

>>> dateRegex1=re.compile('\\d\\d\\d\\d-\\d\\d-\\d\\d')

re.compile()传入一个字符串值,表示正则表达式,此方法返回一个Regex模式对象,简称Regex对象

>>>date1=dateRegex1.search(str)

​ Regex对象的search()方法查找传入的字符串,寻找改字符串中与Regex模式对象相匹配的子串,如果存在,serach()方法返回一个Match对象,如果不存在,serach()方法返回None。

>>> print(date2.group())

Match对象的group()方法,返回实际匹配文本的字符串。

2、使用正则表达式匹配更多模式

1)利用括号对字符串进行分组
>>> import re
>>> regex=re.compile(r'(\d\d\d)-(\d\d\d-\d\d\d\d)')
>>> s=regex.search('电话号码为123-456-7890')
>>> s.group()
'123-456-7890'
>>> s.group(0)
'123-456-7890'
>>> 
>>> s.group(1)
'123'
>>> s.group(2)
'456-7890'
>>> s.groups()
('123', '456-7890')
>>> 

**s.group(A)**解释:

没有参数A或A为0时:返回整个匹配的字符串,不对字符串进行分组

A为1时:返回分组后第一组字符串

A为2时:返回分组后第二组字符串

**groups()**时:获取改字符串的所有分组

注意:字符串中带有括号,该如何分组?
>>> import re
>>> regex=re.compile(r'(\(\d\d\d\))-(\d\d\d-\d\d\d\d)')
>>> s=regex.search('电话号码为(123)-456-7890')
>>> s.group()
'(123)-456-7890'
>>> s.group(1)
'(123)'
>>> s.group(2)
'456-7890'
>>> s.groups()
('(123)', '456-7890')
>>> 
解析:

​ 因为括号在正则表达式中有特殊的含义,所以如果需要匹配带有括号格式的字符串,可以使用" \ " 对括号进行转义。

2)利用管道“ | ”匹配多个分组

①:利用管道字符匹配字符串中两个或多个模式

>>> import re
>>> regex=re.compile(r'帅哥|美女')
>>>=regex.search('他是男的所以是帅哥!')
>>>.group()
'帅哥'
>>>=regex.search('他不是男的,所以她是美女,而不是帅哥!')
>>>.group()
'美女'
>>> 
通过上述代码可以看出当" 帅哥 " “ 美女 ” 都出现在被查找的字符串中,先出现的匹配文本,将作为Match对象返回。

②:使用管道字符 “ | ” 和分组括号 ” () “ 进行匹配

匹配字符串中"嗨,帅哥!",“嗨,美女!”,“嗨,小可爱!” 我们就可以配合使用括号进行分组

>>> import re
>>> regex=re.compile(r'嗨,(美女|帅哥|小可爱)!')
>>> a=regex.search('。。。嗨,美女!你好')
>>> a.group()
'嗨,美女!'
>>> b=regex.search('。。。嗨,帅哥!你好呀!')
>>> b.group()
'嗨,帅哥!'
>>> #因为使用了(),所以可以调用group()带参的方法
>>> a.group(1)
'美女'
>>> b.group(1)
'帅哥'

如果对括号的使用还是一知半解,再看下边的例子

>>> import re
>>> regex=re.compile(r'嗨(美女|帅哥)(你好|你好呀)')
>>> a=regex.search('。。。嗨美女你好呀!')
>>> a.group()
'嗨美女你好'
>>> a.group(1)
'美女'
>>> a.group(2)
'你好'
>>> 
如果需要匹配真正的管道字符,就用倒斜杠转义,即:\|
3)用“ ? ”实现可选匹配{匹配‘零次或一次’}
>>> import re
>>> regex=re.compile(r'(\d\d\d-)?\d\d\d\d\d\d\d')
>>> a=regex.search('号码为123-4567890')
>>> a.group()
'123-4567890'
>>> b=regex.search('号码为4567890')
>>> b.group()
'4567890'
如果需要匹配真正的问号字符,就使用转义字符\?
4)用" * "实现可选匹配{匹配‘零次或多次’}
>>> import re
>>> regex=re.compile(r'(\d\d\d-)*')
>>> a=regex.search('1234567890')
>>> a.group()
''
>>> b=regex.search('123-4567890')
>>> b.group()
'123-'
>>> c=regex.search('123-456-7890')
>>> c.group()
'123-456-'
>>> 
如果需要匹配真正的星号字符,就在正则表达式的星号字符前加上倒斜杠,即
5)用“ + ” 实现可选匹配{匹配‘一次或多次’}
>>> import re
>>> regex=re.compile(r'嗨(帅)+哥')
>>> a=regex.search('嗨哥')
>>> a==None
True
>>> b=regex.search('嗨帅哥')
>>> b.group()
'嗨帅哥'
>>> c=regex.search('嗨帅帅哥')
>>> c.group()
'嗨帅帅哥'
>>> regex=re.compile(r'(帅哥)+')
>>> a=regex.search('帅哥帅哥帅哥')
>>> a.group()
'帅哥帅哥帅哥'
6)用花括号匹配特定次数
如果想要一个分组重复特定的次数,就在正则表达式中该分组的后面,跟上花括号包围的数字。
>>> import re
>>> regex=re.compile(r'老铁\d{3}')
>>> a=regex.search('感谢粉丝送来的礼物,老铁6666666!')
>>> a.group()
'老铁666'
>>> regex=re.compile(r'老铁\d{6}')
>>> a=regex.search('感谢粉丝送来的礼物,老铁6666666!')
>>> a.group()
'老铁666666'
>>> 
还可以使用花括号来指定一个范围,即在花括号中写下最小值、一个逗号和一个最大值。
>>> import re
>>> regex=re.compile(r'\d{3,5}')
>>> a=regex.search('123木头人')
>>> a.group()
'123'
>>> b=regex.search('1234不许动')
>>> b.group()
'1234'
>>> c=regex.search('123456七八九')
>>> c.group()
'12345'
>>> 
花括号中还可以不写第一个或第二个数字,从而不限定最小值或最大值。
>>> import re
>>> regex1=re.compile('\d{,2}')
>>> a=regex1.search('123')
>>> a.group()
'12'
>>> b=regex1.search('1')
>>> b.group()
'1'
>>> c=regex1.search('哈哈,天天开心哦!')
>>> c.group()
''
>>> regex2=re.compile('\d{1,2}')
>>> a=regex2.search('123')
>>> a.group()
'12'
>>> b=regex2.search('1')
>>> b.group()
'1'
>>> c=regex2.search('哈哈,天天开心哦!')
>>> c.group()#报错,c为None
Traceback (most recent call last):
  File "<pyshell#23>", line 1, in <module>
    c.group()
AttributeError: 'NoneType' object has no attribute 'group'
>>> c==None
True
>>> 

3、贪心和非贪心匹配

贪心:Python 的正则表达式默认是“贪心”的,这表示在有二义的情况下,它们会尽可能匹配最长的字符串。

非贪心:Python的正则表达式的非贪心版本是:尽可能匹配最短的字符串,即在匹配的字符结束后跟一个问号。

" * "

>>> import  re
>>> regex=re.compile(r'\d*')
>>> #没有加?时
>>> a=regex.search('123456')
>>> a.group()
'123456'
>>> regex=re.compile(r'\d*?')
>>> #加了?后
>>> a=regex.search('123456')
>>> a.group()
''
>>> 

" + "

>>> import re
>>> regex=re.compile(r'\d+')
>>> #没有加?时
>>> a=regex.search('123456')
>>> a.group()
'123456'
>>> regex=re.compile(r'\d+?')
>>> #加了?后
>>> a=regex.search('123456')
>>> a.group()
'1'
>>> 
虽然可以用于“ * ”和“ + ”, 但意义不大,所以非贪心匹配主要用在“ {} ”
>>> import re
>>> regex=re.compile(r'\d{3,5}')
>>> #没有加?时
>>> a=regex.search('123456')
>>> a.group()
'12345'
>>> regex=re.compile(r'\d{3,5}?')
>>> #加了?后
>>> a=regex.search('123456')
>>> a.group()
'123'
>>> 

4、findall()方法

上述主要使用了Regex对象的search方法,Regex对象还有一个findall()方法。search()方法:将返回一个Match对象,包含被查找字符串中的“第一次”匹配的文本。

findall()方法:将返回一组字符串,包含被查找字符串中的所有匹配。

1)没有使用括号进行分组时:返回字符串列表
>>> import re
>>> regex=re.compile(r'\d\d\d-\d\d\d-\d\d\d\d')
>>> a=regex.search('123-456-7890;098-765-4321')
>>> a.group()
'123-456-7890'
>>> regex.findall('123-456-7890;098-765-4321')
['123-456-7890', '098-765-4321']
2)使用括号进行分组时:返回元组列表
>>> import re
>>> regex=re.compile(r'(\d\d\d)-(\d\d\d)-(\d\d\d\d)')
>>> a=regex.search('123-456-7890;098-765-4321')
>>> a.group()
'123-456-7890'
>>> regex.findall('123-456-7890;098-765-4321')
[('123', '456', '7890'), ('098', '765', '4321')]
>>> 

5、常见字符分类的缩写代码

根据前边的例子,可以知道“ \d ”代表任何数字

缩写字符分类表示
\d0到9的任何数字
\D除0到9的数字以外的任何字符
\w任何字母、数字或下划线字符
\W除字符、数字和下划线以外的任何字符
\s空格、制表符或换行符
\S除表格、制表符和换行符以外的任何字符

6、建立自己的字符分类:[]

1)匹配任意字符
>>> import re
>>> regex=re.compile(r'[1]')
>>> #只匹配数字1
>>> regex.findall('12344321')
['1', '1']
>>> a=regex.search('12344321')
>>> a.group()
'1'
>>> regex=re.compile(r'[a0]')
>>> #只匹配‘a’或0
>>> regex.findall('123a33a00aa0')
['a', 'a', '0', '0', 'a', 'a', '0']
>>> regex=re.compile(r'[a][0]')
>>> #只匹配‘a0’
>>> regex.findall('123a33a00aa0')
['a0', 'a0']
>>> 
2)使用短横线表示字母或数字的范围
>>> import re
>>> regex=re.compile(r'[a-z][0-9]')
>>> regex.findall('a1b23344cd5')
['a1', 'b2', 'd5']
>>> 
字符分类[a-zA-Z0-9]将匹配所有的小写字母、大写字母和数字。
3)"["之后加上一个“ ^ ”,可以得到非字符类

非字符类将匹配不在这个字符类中的所有字符

>>> import re
>>> regex=re.compile(r'[^1]')
>>> regex.findall('1234')
['2', '3', '4']
>>> 

7、插入字符“ ^ ” 和美元字符 “ $ ”

“^”:表明匹配必须发生在被查找文本开始处。

>>> import re
>>> regex=re.compile(r'^\d你好')
>>> regex=re.compile(r'^\d')
>>> regex.findall('abc1')
[]
>>> regex.findall('ab1c')
[]
>>> regex.findall('1abc')
['1']

“$”:表示该字符串必须以这个正则表达式的模式结束。

>>> import re
>>> regex=re.compile(r'\d$')
>>> regex.findall('asd12c')
[]
>>> regex.findall('asd1')
['1']
>>> regex.findall('asd12')
['2']
>>> 

同时使用^和$时,表明整个字符串必须匹配该模式,也就是说,只匹配该字符串的某个子集是不够的。

>>> import re
>>> regex=re.compile(r'^\dhello\d$')
>>> regex.findall('2hellohello1')
[]
>>> regex.findall('1he2')
[]
>>> regex.findall('2hello1')
['2hello1']
>>> regex.findall('2hello2')
['2hello2']
>>> 

8、通配字符

1)" . "句点:匹配除换行以外的所有字符
>>> import re
>>> regex=re.compile(r'.at')
>>> regex.findall('cat,rat,hat')
['cat', 'rat', 'hat']
>>> 
2)“ .* ”

“ . ”:表示除换行以外的所有单个字符

“ * ”:表示前面字符出现零次或多次

>>> import re
>>> regex=re.compile(r'.*at')
>>> regex.findall('cat,flat,hat')
['cat,flat,hat']
>>> regex.findall('catflat')
['catflat']
>>> 
注意:这里返回的是长度为1的字符串列表。

补充:非贪心模式

>>> import re
>>> regex=re.compile(r'.*?at')
>>> regex.findall('cat,flat,hat')
['cat', ',flat', ',hat']
>>> regex.findall('catflat')
['cat', 'flat']
>>> 
注意:这里返回的字符串列表长度大于1
3)“ . ”,re.DOTALL

以上两种都不能匹配换行符;这里可以传入re.DOTALL作为re.compile()的第二的参数。

" . "为例

>>> import re
>>> regex=re.compile('.at',re.DOTALL)
>>> str="""f
at
"""
>>> regex.findall(str)
['\nat']
>>> 

“ .* ”为例

>>> regex=re.compile('.*at',re.DOTALL)
>>> str="""f
at
"""
>>> regex.findall(str)
['f\nat']
>>> 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大脑经常闹风暴@小猿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值