前言
养成一个好的习惯只需要坚持21天,Day16
正则表达式
正则表达式是一种用来匹配字符串的强有力的武器,它用一种描述性的语言来给字符串定义一个规则,凡是符合规则的字符串,我们就认为它“匹配”了,否则,该字符串就是不合法的。
用\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}
其中\d{3}
表示匹配3个数字,\s
可以匹配一个空格,\s+
表示至少有一个空格;\d{3,8}
表示可以匹配3-8个数字。
匹配一个座机号码:\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$
表示必须以数字结束。
re模块
由之前的学习可知,可以使用\
转义,也可以使用Python的r
前缀,使用r
前缀可以避免许多转义的问题。
s = r'ABC\-001' # Python的字符串
# 对应的正则表达式字符串不变:
# 'ABC\-001'
re
模块中,使用match()方法判断是否匹配,匹配成功则返回一个Match对象,否则返回None。如下:
import re
test = '用户输入的测试字符串'
if re.match(r'正则表达式', test): #re.match(r'^\d{3}\-\d{3,8}$', '010-12345')
print('ok')
else:
print('failed')
切分字符串
比如我们一般使用python的split()
函数进行切分:
'a b c'.split(' ')
#['a', 'b', '', 'c']无法识别字符串中连续的空格
使用正则表达式进行切分:
re.split(r'\s+','a b c')
# ['a', 'b', 'c']
如果把划分规则变成逗号:
re.split(r'[\s\,]+','a,b, c d')
# ['a', 'b', 'c', 'd']
再加入分号,进行切分:
re.split(r'[\s\,\;]+','a,b;; c d')
# ['a', 'b', 'c', 'd']
分组
正则表达式除了能够进行字符串的匹配之外,还能提取子串。即对字符串的内容进行分组操作,用()
表示。
^(\d{3})-(\d{3,8})$
中由分别定义了两个组,可以直接从匹配的字符串中提取出区号和本地号码:
m = re.match(r'^(\d{3})-(\d{3,8})$', '083-8250168')
print(m)
# <_sre.SRE_Match object; span=(0, 11), match='083-8250168'>
m.group(0)
#'083-8250168'
m.group(1)
# '083'
m.group(2)
# '8250168'
贪婪
正则匹配默认是贪婪匹配,也就是匹配尽可能多的字符。比如:
re.match(r'^(\d+)(0*)$', '102300').groups()
# ('102300', '') 由于\d+采用贪婪匹配,直接把后面的0全部匹配了,所以0*就只能匹配空字符串了。
在\d+
后面加上一个?
就采用非贪婪匹配了:
re.match(r'^(\d+?)(0*)$', '102300').groups()
# ('1023', '00')
可以使用re.compile()
进行预编译,当正则表达式需要多次使用的时候,可以提高效率!
练习
请尝试写一个验证Email地址的正则表达式。版本一应该可以验证出类似的Email:someone@gmail.com、bill.gates@microsoft.com
import re
re_mail = re.compile(r'^[\w]+\.?[\w]+@[\w]+\.com$')
# 字母一个以上 .有一个或者没有 字母一个以上 @ 字母不限 .com
def is_valid_email(addr):
if re_mail.match(addr):
return True