「正规表示式」(Regualr expression) 看了就让人头晕,一堆难懂的符号与文字。
尤其,正规这两个字让人觉得莫名恐惧。
如果你觉得「正规表示式」的名称让人摸不着头绪,你可以试着从英文来理解,然后在心中为它取一个你比较喜欢的中文名称,也许就不会那么排斥了。
「正规表示式」是Regualr expression 的中文翻译,由两个英文单字组成,regular及expression。
regular 是规则的意思,expression 则是表达的意思,中文翻译把Regualr expression 翻译成「正规表示式」,代表一种有规则、有规律的表达方式。
也有人把Regular expression 翻译为正则表达式、规则运算式、正规表式法。
其实你也可以不必去记这些中文名称,知道Regular expression 就是指,有规则的表达方式就可以了,重要的是让它的功能帮助到你。
接下来我们会介绍正规表示式的功用,比较使用及不使用正规表示式的差异,这个比较文有些冗长,你可以使用快速阅读,直接跳到你需要的操作说明段落。
Python正规表示式的功用
面对「正规表示式」你可能还会有这些问题:
- 一定要学会「正规表示式」吗?
- 「正规表示式」可以干嘛?
- 「正规表示式」功能是什么?
- 「正规表示式」是不是很难?
- 不会「正规表示式」就不能学会写程式吗?
首先,你不一定要会「正规表示式」也是可以写程式。
学会什么都是你的选择,你可以不会「正规表示式」,依然可以编写Python 程式码,让程式运作;就好像你可以不会开车、也不会搭乘交通工具,就是只会走路,你还是可以从台北移动到高雄,只是会比较费力、费时。
「Python正规表示式」可以做什么?
关于这个问题,让我们回到学程式的目的。
你为什么学习编码
最大的目,是要当个收入高、有技术涵养的工程师?跟上趋势,拥有不易被社会淘汰的专长?
这可能是许多人学程式语言的目的。
不过就本质上而言,编写程式语言的目的,是要利用程式帮助我们处理事情,将繁琐复杂的事简单化,让规律的事情自动化。
而「正规表示式」的功用就是:帮你让复杂的程式码规律化、简单化。
学会正规表示式的好处
《Python 自动化的乐趣》这本书将「正规表示式」讲解的很浅显易懂,作者AI Sweigart这么形容,'会'与'不会'「正规表示式」的差异:
会用「正规表示式」(Regualr expression)意味着可以用3个步骤就解决问题,而不需要耗费3,000步才能搞定。
好处总是比较出来才会知道,我们来看看《Python 自动化的乐趣》这本书,所举的例子,让你评估一下是否有必要学会「正规表示式」。
情境是这样的:
设计一个可以辨别电话号码的程式,让你可以在一大堆的资料中,用程式快速帮你抓出电话号码。
要查找的电话号码格式:
02-1111-2222,区码二码数字– 四码数字– 四码数字。
不使用正规表示式
不使用「Python正规表示式」的情况下,我们设计一个名称为isPhoneNumber() 的函式。
首先检查长度是不是12个位元,再依序检查每个位置是数字或是– 符号,每一个条件都必需成立,才会判断为电话号码。
函式内,写满了if 陈述式与for 回圈,一个字元一个字元的检查,资料是不是数字及– 符号,全部符合的情况才会返回True,True 代表某段文字是电话号码,False 代表不是电话号码。
最后面的四行print() 程式码,执行电话号码的辨别工作。
<span style="color:#3a3a3a"><span style="background-color:#ffffff"><span style="background-color:#eeeeee"><code>>>> def isPhoneNumber(text):
>>> if len(text) != 12:
>>> return False
>>> for i in range(0,2):
>>> if not text[i].isdecimal():
>>> return False
>>> if text[2] != '-':
>>> return False
>>> for i in range(4,7):
>>> if not text[i].isdecimal():
>>> return False
>>> if text[7] != '-':
>>> return False
>>> for i in range(8,11):
>>> if not text[i].isdecimal():
>>> return False
>>> return True
>>>
>>> print('this is a number: 02-1234-5555')
>>> print(isPhoneNumber('02-1234-5555'))
>>> print('this is a number: oh no! regular expression')
>>> print(isPhoneNumber('oh no! regular expression'))</code></span></span></span>
执行程式后,得到的结果
<span style="color:#3a3a3a"><span style="background-color:#ffffff"><span style="background-color:#eeeeee"><code>this is a number: 02-1234-5555
True
this is a number: oh no! regular expression
False</code></span></span></span>
成功辨识出02-1234-5555 是电话号码,而oh no! regular expression 不是电话号码。
接着我们再将最后四行的print() 程式码调整一下,搭配for 回圈与if 陈述式,减少你打一大堆print(),调整后如下:
<span style="color:#3a3a3a"><span style="background-color:#ffffff"><span style="background-color:#eeeeee"><code>>>> Data = 'Please call David at 02-8888-1688 by today. 02-9888-9898 is his office number.'
>>> for i in range(len(Data)):
>>> number = Data [i:i+12]
>>> if isPhoneNumber(number):
>>> print('Phone Number: ' + number)
>>> print('Please call him/her as soon as possible.')</code></span></span></span>
执行结果如下方所示:
<span style="color:#3a3a3a"><span style="background-color:#ffffff"><span style="background-color:#eeeeee"><code>Phone Number: 02-8888-1688
Phone Number: 02-9888-9898
Please call him/her as soon as possible.</code></span></span></span>
这是不使用正规表示式,来找寻、比对资料的方法,你需要帮每个字元设定条件,以判别是不是电话号码的格式。
使用正规表示式
而如果使用「Python正规表示式」来检查,会是什么状况呢?
「正规表示式」有强大的比对功能,为多种字元条件设定了特定的符号,例如要找数字,以\d表示,就会让Python 去判别字元是不是数字。
一样是针对找电话号码情境,使用「正规表示式」的程式码会是这样:
<span style="color:#3a3a3a"><span style="background-color:#ffffff"><span style="background-color:#eeeeee"><code>>>> import re
>>> phoneNumRegex = re.compile(r'\d\d-\d\d\d\d-\d\d\d\d')
>>> result = phoneNumRegex.findall('Please call David at 02-8888-1688 by today. 02-9888-9898 is his office number.')
>>> number = ', '.join(result)
>>> print('Phone Number: ' + number)
>>> print('Please call him/her as soon as possible.')</code></span></span></span>
没错,如果你会使用「正规表示式」,就可以很简洁的你做一个功能一样的小程式。
执行结果:
<span style="color:#3a3a3a"><span style="background-color:#ffffff"><span style="background-color:#eeeeee"><code>Phone Number: 02-8888-1688, 02-9888-9898
Please c