Python学习之正则

作者 : 开心源码 本文共3182个字,预计阅读时间需要8分钟 发布时间: 2022-05-11 共91人阅读

Python学习目录

  1. 在Mac下用Python3
  2. Python学习之数据类型
  3. Python学习之函数
  4. Python学习之高级特性
  5. Python学习之函数式编程
  6. Python学习之板块
  7. Python学习之面向对象编程
  8. Python学习之面向对象高级编程
  9. Python学习之错误调试和测试
  10. Python学习之IO编程
  11. Python学习之进程和线程
  12. Python学习之正则
  13. Python学习之常使用板块
  14. Python学习之网络编程

正则表达式是一种使用来匹配字符串的强有力的武器。它的设计思想是使用一种形容性的语言来给字符串定义一个规则,但凡符合规则的字符串,我们就认为它“匹配”了,否则,该字符串就是不合法的。

正则

基本

在正则表达式中,假如直接给出字符,就是准确匹配。使用\d能匹配一个数字,\w能匹配一个字母或者数字,所以:

  • '00\d'能匹配'007',但无法匹配'00A'
  • '\d\d\d'能匹配'010'
  • '\w\w\d'能匹配'py3'

.能匹配任意字符,所以:

  • 'py.'能匹配'pyc''pyo''py!'等等。

要匹配变长的字符,在正则表达式中,使用*表示任意个字符(包括0个),使用+表示至少一个字符,使用?表示0个或者1个字符,使用{n}表示n个字符,使用{n,m}表示n-m个字符:

来看一个复杂的例子:\d{3}\s+\d{3,8}

我们来从左到右解读一下:

  1. \d{3}表示匹配3个数字,例如'010'
  2. \s能匹配一个空格(也包括Tab等空白符),所以\s+表示至少有一个空格,例如匹配' '' '等;
  3. \d{3,8}表示3-8个数字,例如'1234567'

综合起来,上面的正则表达式能匹配以任意个空格隔开的带区号的电话号码。

假如要匹配'010-12345'这样的号码呢?因为'-'是特殊字符,在正则表达式中,要使用'\'转义,所以,上面的正则是\d{3}\-\d{3,8}

但是,依然无法匹配'010 - 12345',由于带有空格。所以我们需要更复杂的匹配方式。

进阶

要做更准确地匹配,能使用[]表示范围,比方:

  • [0-9a-zA-Z\_]能匹配一个数字、字母或者者下划线;
  • [0-9a-zA-Z\_]+能匹配至少由一个数字、字母或者者下划线组成的字符串,比方'a100''0_Z''Py3000'等等;
  • [a-zA-Z\_][0-9a-zA-Z\_]*能匹配由字母或者下划线开头,后接任意个由一个数字、字母或者者下划线组成的字符串,也就是Python合法的变量;
  • [a-zA-Z\_][0-9a-zA-Z\_]{0, 19}更准确地限制了变量的长度是1-20个字符(前面1个字符+后面最多19个字符)。

A|B能匹配A或者B,所以(P|p)ython能匹配'Python'或者者'python'

^表示行的开头,^\d表示必需以数字开头。

$表示行的结束,\d$表示必需以数字结束。

你可可以注意到了,py也能匹配'python',但是加上^py$就变成了整行匹配,就只可以匹配'py'了。

re板块

有了准备知识,我们即可以在Python中用正则表达式了。Python提供re板块,包含所有正则表达式的功可以。因为Python的字符串本身也使用\转义,所以要特别注意:

s = 'ABC\\-001' # Python的字符串# 对应的正则表达式字符串变成:# 'ABC\-001'

因而我们强烈建议用Python的r前缀,就不使用考虑转义的问题了:

s = r'ABC\-001' # Python的字符串# 对应的正则表达式字符串不变:# 'ABC\-001'

先看看如何判断正则表达式能否匹配:

>>> import re>>> re.match(r'^\d{3}\-\d{3,8}$', '010-12345')<_sre.SRE_Match object; span=(0, 9), match='010-12345'>>>> re.match(r'^\d{3}\-\d{3,8}$', '010 12345')>>>

match()方法判断能否匹配,假如匹配成功,返回一个Match对象,否则返回None。常见的判断方法就是:

test = '使用户输入的字符串'if re.match(r'正则表达式', test):    print('ok')else:    print('failed')

分组

除了简单地判断能否匹配之外,正则表达式还有提取子串的强大功可以。使用()表示的就是要提取的分组(Group)。比方:

^(\d{3})-(\d{3,8})$分别定义了两个组,能直接从匹配的字符串中提取出区号和本地号码:

>>> m = re.match(r'^(\d{3})-(\d{3,8})$', '010-12345')>>> m<_sre.SRE_Match object; span=(0, 9), match='010-12345'>>>> m.group(0)'010-12345'>>> m.group(1)'010'>>> m.group(2)'12345'

假如正则表达式中定义了组,即可以在Match对象上使用group()方法提取出子串来。

注意到group(0)永远是原始字符串,group(1)group(2)……表示第1、2、……个子串。

提取子串非常有使用。来看一个更凶残的例子:

>>> t = '19:05:30'>>> m = re.match(r'^(0[0-9]|1[0-9]|2[0-3]|[0-9])\:(0[0-9]|1[0-9]|2[0-9]|3[0-9]|4[0-9]|5[0-9]|[0-9])\:(0[0-9]|1[0-9]|2[0-9]|3[0-9]|4[0-9]|5[0-9]|[0-9])$', t)>>> m.groups()('19', '05', '30')

这个正则表达式能直接识别合法的时间。但是有些时候,使用正则表达式也无法做到完全验证,比方识别日期:

'^(0[1-9]|1[0-2]|[0-9])-(0[1-9]|1[0-9]|2[0-9]|3[0-1]|[0-9])$'

对于'2-30''4-31'这样的非法日期,使用正则还是识别不了,或者者说写出来非常困难,这时就需要程序配合识别了。

贪婪匹配

最后需要特别指出的是,正则匹配默认是贪婪匹配,也就是匹配尽可可以多的字符。举例如下,匹配出数字后面的0

>>> re.match(r'^(\d+)(0*)$', '102300').groups()('102300', '')

因为\d+采使用贪婪匹配,直接把后面的0一律匹配了,结果0*只可以匹配空字符串了。

必需让\d+采使用非贪婪匹配(也就是尽可可以少匹配),才可以把后面的0匹配出来,加个?即可以让\d+采使用非贪婪匹配:

>>> re.match(r'^(\d+?)(0*)$', '102300').groups()('1023', '00')

编译

当我们在Python中用正则表达式时,re板块内部会干两件事情:

  1. 编译正则表达式,假如正则表达式的字符串本身不合法,会报错;
  2. 使用编译后的正则表达式去匹配字符串。

假如一个正则表达式要重复用几千次,出于效率的考虑,我们能预编译该正则表达式,接下来重复用时就不需要编译这个步骤了,直接匹配:

>>> import re# 编译:>>> re_telephone = re.compile(r'^(\d{3})-(\d{3,8})$')# 用:>>> re_telephone.match('010-12345').groups()('010', '12345')>>> re_telephone.match('010-8086').groups()('010', '8086')

编译后生成Regular Expression对象,因为该对象自己包含了正则表达式,所以调使用对应的方法时不使用给出正则字符串。

下一篇:Python学习之常使用板块

说明
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是摆设,本站源码仅提供给会员学习使用!
7. 如遇到加密压缩包,请使用360解压,如遇到无法解压的请联系管理员
开心源码网 » Python学习之正则

发表回复