正则表达式语法规则
re模块
正则表达式是一种用来匹配字符串的强有力的武器。它的设计思想是用一种描述性的语言来给字符串定义一个规则,凡是符合规则的字符串,我们就认为它"匹配"了,否则,该字符串就是不合法的。
- Python提供re模块,包含所有正则表达式的功能。由于Python的字符串本身也用
\转义
,所以要特别注意:
python
s = 'ABC\\-001' # Python的字符串
# 对应的正则表达式字符串变成:
# 'ABC\-001'
因此我们强烈建议使用Python的r前缀
,就不用考虑转义的问题了:
python
s = r'ABC\-001' # Python的字符串
# 对应的正则表达式字符串不变:
# 'ABC\-001'
先看看如何判断正则表达式是否匹配:
python
import re
a = re.match(r'^\d{3}\-\d{3,8}$', '010-12345')
print(a)
b = re.match(r'^\d{3}\-\d{3,8}$', '010 12345')
print(b)
match()方法判断是否匹配,如果匹配成功,返回一个Match对象,否则返回Non
e。
使用
python
import re
test = '用户输入的字符串'
if re.match(r'正则表达式', test):
print('ok')
else:
print('failed')
切分字符串
用正则表达式切分字符串比用固定的字符更灵活,请看正常的切分代码:
python
c = 'a b c'.split(' ')
print(c)
#['a', 'b', '', '', 'c']
- 无法识别连续的空格
正则切分
python
d = re.split(r'\s+', 'a b c')
print(d)
#['a', 'b', 'c']
无论多少个空格都可以正常分割。加入,
试试:
python
e = re.split(r'[\s\,]+', 'a,b, c d')
print(e)
#['a', 'b', 'c', 'd']
再加入;
试试:
python
f = re.split(r'[\s\,\;]+', 'a,b;; c d')
print(f)
#['a', 'b', 'c', 'd']
分组
除了简单地判断是否匹配之外,正则表达式还有提取子串
的强大功能。用()
表示的就是要提取的分组(Group)
。
- 比如:
^(\d{3})-(\d{3,8})$
分别定义了2个组,可以直接从匹配的字符串中提取出区号和本地号码
:
python
g = re.match(r'^(\d{3})-(\d{3,8})$', '010-12345')
print(g.group(0))
print(g.group(1))
print(g.group(2))
#010-12345
#010
#12345
如果正则表达式中定义了组,就可以在Match对象上用group()方法
提取出子串来。
- 注意到
group(0)永远是与整个正则表达式相匹配的字符串
,group(1)、group(2)......表示第1、2、......个子串。
提取子串非常有用。来看一个更凶残的例子:
python
h = '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])$',h)
print(m.groups())
#('19', '05', '30')
这个正则表达式可以直接识别合法的时间。但是有些时候,用正则表达式也无法做到完全验证,比如识别日期:
python
'^(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'
这样的非法日期,用正则还是识别不了,或者说写出来非常困难,这时就需要程序配合识别了。
贪婪匹配
当我们在Python中使用正则表达式时,re模块内部会干两件事情:
- 编译正则表达式,如果正则表达式的语法不合法,会报错;
- 用编译后的正则表达式去匹配字符串。
如果一个正则表达式要重复使用几千次,出于效率的考虑,我们可以·预编译该正则表达式·,接下来重复使用时就不需要编译这个步骤了,直接匹配:
python
# 编译:
re_telephone = re.compile(r'^(\d{3})-(\d{3,8})$')
# 使用:
a2 = re_telephone.match('010-12345').groups()
print(a2)
# ('010', '12345')
a3 = re_telephone.match('010-8086').groups()
print(a3)
# ('010', '8086')