正则表达式(Regular Expression,常简写为regex、regexp或re),是文本处理中的一个重要概念。正则表达式通常被用来检索、替换那些符合某个模式(规则)的文本,简单地说,正则表达式就是一门专门用于字符串处理的增强语法。为了了解什么是正则表达式,我们先看一个简单的示例。
问题:在字符串 “我叫张三今年28岁,身高182cm,体重90kg,以前的手机号是13912345678,现在的手机号是:18812345678, 家里的电话是66658933,身份证号是 340403198501011234”
中找出所有的数字序列,如 28,182,90等。
如果我们直接选择编写程序来完成,自然是可以实现的,以下的代码即可完成。
def findnumbers(s):
p = 0
res = []
for i in range(0, len(content)):
if (p == 0 or not s[i-1].isdigit()) and s[i].isdigit():
p = i
elif s[i].isdigit() and (i + 1 == len(content) or not s[i+1].isdigit()):
res.append(s[p:i+1])
return res
以这段代码中,我们编写了一个findnumber(s) 函数,通过这个函数,我们对输入的字符串s的每个字符进行分析,分别找到以数据开头字符和结尾字符的位置,那么就可以将所有的数字提取出来。程序执行以后,我们可以得到以下的输出:
findnumbers: ['28', '182', '90', '13912345678', '18812345678', '66658933', '340403198501011234']
可见,所有的数字组合都按顺序找到了,达到了预期的目的。虽然任务完成了,但是我们发现有以下两个问题:首先,这个操作是复杂的,对于算法的实现和边界的判断有一定的复杂性,对很多同学来说在代码的编写上需要花费很多时间,包括编写、调试和修改;其次,这个算法兼容性太差,仅能满足这个简单的需求,如果我们提出新的要求,比如说对这些数字再进行筛选或分组,那么我们又要修改代码,才能满足新的要求。
那么有没有一种方式不需要修改代码,只需要指定我要查找的数据格式,就能把指定的内容返回呢?答案是肯定的,相信读者一定想到了就是正则表达式。那么就针对找数字这一相同问题,我们来看一下正则表达式如何实现,代码如下所示:
import re
content='我叫张三今年28岁,身高182cm,体重90kg,以前的手机号是13912345678,现在的手机号是:18812345678, 家里的电话是66658933,身份证号是 340403198501011234'
regex=re.compile('[0-9]+')
res = regex.findall(content)
print('all numbers:', res)
程序运行以后,可以得到相同的查询结果:
all numbers: ['28', '182', '90', '13912345678', '18812345678', '66658933', '340403198501011234']
由于代码量只有寥寥几行,所以在没有任何说明之前,相信读者可以看懂大致内容,即首先我们引入了正则表达式的命名空间 re,然后定义了一个正则表达式的对象 regex,其中 regex=re.compile(’[0-9]+’) 是其筛选规则,而 regex.findall(content),则是执行过程,即在字符串查找相应的数字串。代码中唯一难以理解的就是 [0-9]+
,它指定了所要查询的格式为连续长度的数字,其中[0-9]表示每个字符的内容只能是0-9之间的数字,而+表示其连续的长度为不小于1。所以, [0-9]+
就是表示长度不小于1的连续数字的字符串。
通过这个示例,我们可以看到,利用正则表达式,只需要指定数据的格式,即可使用程序的re模块定义查询对象后,再通过执行查询操作找到我们所需要的内容。通过正则表达式,我们可以进一步对字符串操作进行抽象,将原先先理解需求,然后写代码实现的过程,变为将需求转换为字符串的正则表达式,然后让re模块去执行的过程。这种转换不仅大大简化了复杂字符串操作,同时也极大的提高了代码的质量,毕竟大部分程序员写的代码肯定没有由官方提供的re模块质量高。
附:参考代码
import re
pattern= R"1(3[0-9]|5[0-35-9]|8[025-9]){1}[0-9]{8}"
pattern = R"[0-9]+"
content='我以前的手机号是:13912345678,现在的手机号是:18812345678, 家里的电话是66658933,身份证号是 340403198501011234'
content0 = '18815694732'
regex=re.compile(R"1(3[0-9]|5[0-35-9]|8[025-9]){1}[0-9]{8}")
res = regex.findall(content)
print('regex.findall', res)
res = re.search(pattern, content)
print(res)
print('findall', re.findall(pattern, content))
pattern = 'abc'
content="abcd bcd abc cadbabcgfe"
print('findall', re.findall(pattern, content))