Python中的正则表达式
4个小节,预计用时20分钟。
正则表达(Regular Expression,或简称RegEx)是编程语言中用来搜索文本中格式匹配的重要手段。比如说判断一个字符串是否包含合法的Email地址、找到文本中电话号码形式的字符出现的位置等等。
本教程将教会大家如何在Python中使用正则表达。
本教程基于Python 3.7。
原创者:我小宋 | 修改校对:SofaSofa TeamM |
0. 准备
Python3中有自带的正则表达模块re
,和其他模块一样,我们只需要import
即可加载。
import re
下面的小例子,就是查找字符串中所有的in
。通常我们在正则表达的格式前面加上r
,比如下面的r"in"
。
string = "Taiwan is a province in China."
x = re.findall(r"in", string)
print(x)
['in', 'in', 'in']
1. 入门正则表达式
正则表达式本身也是用字符串表示,通常在引号前加上r
。我们首先了解如何用字符来描述字符。
\d
表示一个数字;
\w
表示一个数字、一个字母或者一个下划线;
\s
表示一个空格;
?
表示任意0个或者一个字符;
.
表示任意一个字符;
*
表示任意一个字符串,甚至可以是空字符串;
+
表示任意一个非空的字符串;
[]
表示一个集合。
下面的例子中r"i\w\w"
表示一个长度为3的字符串,第一个字符为i
,第二三个字符是一个字母或者数字或者下划线。
所以我们得到的结果是int
和ing
。
string = "I'm interested in buying the new BMW i3 car."
x = re.findall(r"i\w\w", string)
print(x)
['int', 'ing']
r"i\d"
表示一个长度为2的字符,第一个字符为i
,第二个字符是数字。
string = "I'm interested in buying the new BMW i3 car."
x = re.findall(r"i\d", string)
print(x)
['i3']
r"\w*i\w*"
表示包含字母i
的子字符串。
string = "I'm interested in buying the new BMW i3 car."
x = re.findall(r"\w*i\w*", string)
print(x)
['interested', 'in', 'buying', 'i3']
r"\w*[abc]\w*"
表示包含字母a
或者b
或者c
的子字符串。
string = "I'm interested in buying the new BMW i3 car."
x = re.findall(r"\w*[abc]\w*", string)
print(x)
['buying', 'car']
2. [ ]集合的使用
上一个例子我们看到了集合符号[ ]
的一个例子。其实集合还有更丰富的用法,例如:
[125]
表示1
或者2
或者5
;
[3-7]
表示3
到7
的一个数字,也就是3
、4
、5
、6
、7
;
[0-9+]
表示0
到9
的一个数字或者+
;
[a-z]
表示a
到z
的一个小写字母;
[a-zA-Z]
表示a
到z
的或者A
到Z
的一个大写字母;
[^xyz]
表示除了x
、y
、z
以外的任意一个字符;
[]{n}
表示一个长度为n的子字符串,每个字符都来自集合;
[]{n,m}
表示一个长度大于等于n小于等于m的子字符串,每个字符都来自集合。
r"2[0-9]{3}"
表示以2开头的所有的四位数。下面的例子中,我们提取了句子中所有的年份。
string = "克洛泽参加的4届世界杯中,他一共打入16球,其中2002世界杯5球,2006德国世界杯5球,2010南非世界杯4球,2014巴西世界杯2球。"
x = re.findall(r"2[0-9]{3}", string)
print(x)
['2002', '2006', '2010', '2014']
3. re中的常见方法
re
中的常见用法有re.search
、re.match
、re.findall
、re.split
、re.sub
。
3.1 re.search
re.search(pattern, string)
是搜索string
中符合pattern
的第一个字符串,返回一个SRE_Match
对象。下面的例子中,我们搜索句子中第一个的年份;如果没有找到,则返回None。
string = "克洛泽参加的4届世界杯中,他一共打入16球,其中2002世界杯5球,2006德国世界杯5球,2010南非世界杯4球,2014巴西世界杯2球。"
x = re.search(r"2[0-9]{3}", string)
print('第一个年份:', x.group())
print('在string的范围:', x.span())
print('开头的位置:', x.start())
print('结束的位置(不包含):', x.end())
第一个年份: 2002
在string的范围: (24, 28)
开头的位置: 24
结束的位置(不包含): 28
3.2 re.match
re.match(pattern, string)
是对string
和pattern
进行匹配,返回一个SRE_Match
对象,如果匹配失败则返回None。match
是search
的特殊情况,match
必须从string
的第一个字符开始匹配,要求更严格。
string = "克洛泽参加的4届世界杯中,他一共打入16球,其中2002世界杯5球,2006德国世界杯5球,2010南非世界杯4球,2014巴西世界杯2球。"
x = re.search(r"2[0-9]{3}", string)
if x:
print('re.search成功')
else:
print('re.search失败')
x = re.match(r"2[0-9]{3}", string)
if x:
print('re.match成功')
else:
print('re.match失败')
re.search成功
re.match失败
3.3 re.findall
re.findall(pattern, string)
是从string
找到所有符合pattern
的子字符串,返回一个list,如果没有找到则返回一个空的list。
string = "克洛泽参加的4届世界杯中,他一共打入16球,其中2002世界杯5球,2006德国世界杯5球,2010南非世界杯4球,2014巴西世界杯2球。"
x = re.findall(r"2[0-9]{3}", string)
print(x)
['2002', '2006', '2010', '2014']
3.4 re.split
re.split(pattern, string)
是从string
找到所有符合pattern
的子字符串,并以这些子字符串为切割点,对原字符串进行分隔,返回得到一个list,每个元素是被分割的子字符串。
如果没有找到则返回一个只包含string
的list。
string = "克洛泽参加的4届世界杯中,他一共打入16球,其中2002世界杯5球,2006德国世界杯5球,2010南非世界杯4球,2014巴西世界杯2球。"
x = re.split(r"2[0-9]{3}", string)
print(x)
['克洛泽参加的4届世界杯中,他一共打入16球,其中', '世界杯5球,', '德国世界杯5球,', '南非世界杯4球,', '巴西世界杯2球。']
3.5 re.sub
re.split(pattern, replace, string)是查找替换的功能,从string
找到所有符合pattern
的子字符串,并替换成replace
。
string = "克洛泽参加的4届世界杯中,他一共打入16球,其中2002世界杯5球,2006德国世界杯5球,2010南非世界杯4球,2014巴西世界杯2球。"
x = re.sub(r"2[0-9]{3}", "某某年", string)
print(x)
克洛泽参加的4届世界杯中,他一共打入16球,其中某某年世界杯5球,某某年德国世界杯5球,某某年南非世界杯4球,某某年巴西世界杯2球。
4. 练习:利用Python正则表达判断合法Email地址
def IsValidEmail(email):
pattern = r"[a-zA-Z0-9_+\.-]+@\w+\.\w+"
if not re.match(pattern, email):
return False
return True
email1 = 'submit@sofasofa.io'
print('Is %s valid? %s\n'%(email1, IsValidEmail(email1)))
email2 = 'a?b@gmail'
print('Is %s valid? %s\n'%(email2, IsValidEmail(email2)))
email3 = '123@456@qq.com'
print('Is %s valid? %s\n'%(email3, IsValidEmail(email3)))
Is submit@sofasofa.io valid? True
Is a?b@gmail valid? False
Is 123@456@qq.com valid? False