[关闭]
@yanglt7 2018-12-03T10:25:13.000000Z 字数 2473 阅读 628

Python22_正则表达式

Python


精确匹配

在正则表达式中,如果直接给出字符,就是精确匹配。

匹配变长的字符

要匹配变长的字符,在正则表达式中,

* 任意个字符(包括0个)
+ 至少一个字符
? 0 个或 1 个字符
{n} n个字符
{n,} 至少n个字符
{n,m} n至m个字符
[\u4E00-\u9FA5] 连续出现的汉字,是unicode编码

匹配特殊字符

范围匹配

要做更精确地匹配,可以用 [] 表示范围,比如:

[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 个字符)。

[0-9] 表示 0-9 任意字符都可,[0-9]{9} 表示区间 0 至 9 出现 9 次;

[^1] 表示任意字符只要不是 1 即可;

[.] 就是 . ,无特殊含义。中括号里的字符都不再有特殊含义;

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

^ 表示行的开头,^\d 表示必须以数字开头。^1 代表一行的开头必须是 1。

表示必须以数字结束。1$ 代表一行必须以 1 结尾。

re模块

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

s = r'ABC-001' # Python的字符串
# 对应的正则表达式字符串不变:
# 'ABC-001'
建议使用 Python 的 r 前缀,就不用考虑转义的问题.

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

  1. >>> import re
  2. >>> re.match(r'^\d{3}\-\d{3,8}$', '010-12345')
  3. <_sre.SRE_Match object; span=(0, 9), match='010-12345'>
  4. >>> re.match(r'^\d{3}\-\d{3,8}$', '010 12345')
  5. >>>
  6. test = '用户输入的字符串'
  7. if re.match(r'正则表达式', test):
  8. print('ok')
  9. else:
  10. print('failed')

切分字符串

用正则表达式来把不规范的输入转化成正确的数组。

  1. >>> 'a b c'.split(' ')
  2. ['a', 'b', '', '', '', 'c']
  3. >>> re.split(r'\s+','a b c')
  4. ['a', 'b', 'c']
  5. >>> re.split(r'[\s\,]+','a,b, c d')
  6. ['a', 'b', 'c', 'd']
  7. >>> re.split(r'[\s\,\;]+','a,b;;c d')
  8. ['a', 'b', 'c', 'd']

分组

提取子串。用 () 表示的就是要提取的分组(Group)。比如:

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

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

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

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

贪婪匹配

正则匹配默认是贪婪匹配,也就是匹配尽可能多的字符,顺序是从右往左匹配。举例如下,匹配出数字后面的0:

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

由于 \d+ 采用贪婪匹配,直接把后面的 0 全部匹配了,结果 0* 只能匹配空字符串了。

必须让 \d+ 采用非贪婪匹配(也就是尽可能少匹配),顺序是从左往右匹配,才能把后面的 0 匹配出来,加个 ? 就可以让 \d+ 采用非贪婪匹配:

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

编译

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

编译正则表达式,如果正则表达式的字符串本身不合法,会报错;

用编译后的正则表达式去匹配字符串。

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

  1. >>> import re
  2. # 编译:
  3. >>> re_telephone = re.compile(r'^(\d{3})-(\d{3,8})$')
  4. # 使用:
  5. >>> re_telephone.match('010-12345').groups()
  6. ('010', '12345')
  7. >>> re_telephone.match('010-8086').groups()
  8. ('010', '8086')
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注