温馨提示:
1. 部分包含数学公式或PPT动画的文件,查看预览时可能会显示错乱或异常,文件下载后无此问题,请放心下载。
2. 本文档由用户上传,版权归属用户,汇文网负责整理代发布。如果您对本文档版权有争议请及时联系客服。
3. 下载前请仔细阅读文档内容,确认文档内容符合您的需求后进行下载,若出现内容与标题不符可向本站投诉处理。
4. 下载文档时可能由于网络波动等原因无法下载或下载错误,付费完成后未能成功下载的用户请联系客服处理。
网站客服:3074922707
正则
指引
CMYCMMYCYCMYK正指引(第2版)fy.pdf 1 2018/9/6 10:48:25II 引子:关于正则表达式 内 容 简 介 本书综合作者自己遇到的实际问题,以及其他开发人员咨询的问题,总结出一套巧妙运用正则表达式的办法,并通过具体的例子指导读者拆解、分析问题。全书分为三部分:第一部分主要讲解正则表达式的基础知识,涵盖了正则表达式中常见的各种功能和结构;第二部分主要讲解关于正则表达式的更深入的知识,详细探讨了编码问题、匹配原理、解题思路;第三部分将之前介绍的各种知识落实到常用语言.NET、Java、JavaScript、PHP、Python、Ruby、Objective-C、Golang 中,在详细介绍了在这些语言中正则表达式的具体用法之外,还辨析了版本之间的细微差异。本书既可以作为专门的学习用书,也可以作为备查的参考手册。本书适合经常需要进行文本处理(比如日志分析或网络运维)的技术人员、熟悉常用开发语言的程序员,以及已经对正则表达式有一定了解的读者阅读。未经许可,不得以任何方式复制或抄袭本书之部分或全部内容。版权所有,侵权必究。图书在版编目(CIP)数据 正则指引/余晟著.2 版.北京:电子工业出版社,2018.11 ISBN 978-7-121-35130-3 .正.余.正则表达式.TP301.2 中国版本图书馆 CIP 数据核字(2018)第 224858 号 策划编辑:张春雨 责任编辑:刘 舫 印 刷:装 订:出版发行:电子工业出版社 北京市海淀区万寿路 173 信箱 邮编:100036 开 本:787980 1/16 印张:24.5 字数:577 千字 版 次:2012 年 5 月第 1 版 2018 年 11 月第 2 版 印 次:2018 年 11 月第 1 次印刷 定 价:89.00 元 凡所购买电子工业出版社图书有缺损问题,请向购买书店调换。若书店售缺,请与本社发行部联系,联系及邮购电话:(010)88254888,88258888。质量投诉请发邮件至 ,盗版侵权举报请发邮件至 。本书咨询联系方式:010-51260888-819,。引子:关于正则表达式 III 引子:关于正则表达式 正则表达式正则表达式这个名字看起来总有点古怪,概念似乎也不简单,甚至需要用一整本书来讲解。可是,它到底是什么呢?同为技术人员,我相信你总会与字符串打交道,相应的,各种语言也都提供了与字符串有关的函数。我们先看下面几个问题,用字符串函数是如何解决的(下面的代码使用 Python 语言,它很直观,正文里有基础的介绍。现在,你只需要知道 def 是定义函数的关键词即可)。引入正则表达式 1.判断字符 ch 是否是数字字符 def isDigit(ch):return ch=0 or ch=1 or ch=9 2.判断字符串 str 是否是电话号码(为简单起见,现在只考虑固定电话号码,也就是长度在78 位之间的数字字符串,且第一位不为 0)def isPhoneNum(str):if len(str)=7 and len(str)=8 and str0!=0:for ch in str:if not isDigit(ch):return false return true return false 任务的复杂度并没有增加太多,程序的复杂度增加了很多倍;如果你不同意,那么,来一个更复杂的。3.找出一段文本中所有的电话号码 最直接的办法是,在字符串中的每个位置截取 78 个字符,调用之前的isPhoneNum()。这么做看起来没问题,只是效率太低。当然,做点改进也不难,加上一个前置条件,只在“当前字符为数字字符”的情况下调用IV 引子:关于正则表达式 isPhoneNum()。这样效率倒是改进了,但是还有问题没有解决:要求找到的是长度大于等于 7 个字符、小于等于 8 个字符的“数字字符串”,而不是“子字符串”也就是说,假如数字字符串是 64240000,需要将它找出来;如果数字字符串是 13800138000,则需要忽略它,以及其中的任何子串(比如 13800138、00138000)。所以,用isPhoneNum()找出字符串之后,还需要保证它之前的字符不是数字字符,之后的字符也不是数字字符。看起来很简单,但合格的程序员一定要考虑边界问题,避免越界错误:如果当前字符是整段文本的第一个字符,则不需要判断之前的字符,因为它不存在;同样,如果找出的字符串在整段文本的末尾,则不需要判断之后的字符,因为它同样不存在 到现在为止,即便只是找到最简单的固定电话号码,程序也非常复杂,难以维护。如果要查找的是形式更多变的文本,比如带区号的电话号码(021-64240000 或者 03718888888)、手机号码(13800138000、+8613800138000 或者 013800138000),程序更是不可想象,更不用说文件路径名、URL 地址、电子邮件地址了!然而,日常开发中我们又确实经常需要面对这类任务,有什么更好的办法呢?正则表达式就是解决这类问题的万能药。虽然许多人有点看不起它,觉得不入流,一些科班教材里也不会花太多篇幅来介绍它,但它确实是解决问题的利器之前提到的三个例子,用正则表达式都可以轻松解决。引入正则表达式之后 1.判断字符 ch 是否是数字字符 def isDigit(ch):return re.search(ch,0-9)!=None 看起来很复杂,其实并不复杂:这里真正要关心的就是正则表达式0-9,它表示“从 0 到9 之间的任意字符”,很形象吧?re.search()是正则表达式运算函数,它判断 ch 能否由正则表达式0-9匹配,可以则返回一个结果,否则返回 None(这些细节正文中会讲到)。2.判断字符串 str 是否是电话号码 def isPhoneNum(str):return re.search(str,1-90-96,7)!=None 这个正则表达式最开始是1-9,表示第一个字符必须是 19 之间的数字字符;之后是0-96,7,表示长度在 6 和 7 之间,由 09 之间的数字字符组成的字符串(两部分加起来,整个字符串的长度在 7 和 8 之间)。要解决的问题复杂了,正则表达式仍然直观形象。3.找出一段文本中所有的固定电话号码 def findNumStr(str):return re.findall(str,(?!0-9)1-90-96,7(?!0-9)引子:关于正则表达式 V 这个正则表达式之前多出了(?!0-9),表示“之前不能是0-9”;之后多出了(?!0-9),表示“之后不能是0-9”。虽然稍微复杂点,但意思明确,而且不难理解。re.findall()的意思也很明显:找到所有这样的字符串。可以想象,循着这种思路,查找更复杂的电话号码、手机号码等任务都不难解决。更重要的是,之前需要许多行语句才能完成的任务,现在基本上只需要一个正则表达式、一条语句就可以完成。正因为如此,不少人虽然认为正则表达式不够花哨、漂亮,却不得不承认它是一种“匕首应用”匕首,没有十八般兵刃那么气派,关键时候却不可或缺,所以值得花时间练练。同样,正则表达式虽然不能用来显摆,但总有派得上用场的地方,花时间练练绝不是坏事。即便你的工作不是纯粹的文本处理(比如日志分析),也总会有用到正则表达式的地方(比如查找和修改源代码),所以我希望,这本书能陪伴你练出一身正则表达式的好功夫,在关键场合能亮出称手的工具。最后,为了传承经典教科书的良好习惯,附上正则表达式的“科班史”。正则表达式发源于与计算机密切相关的两个领域:计算理论和形式语言。20 世纪 40 年代,两位神经生理学家 Warren McCulloch 和 Walter Pitts 发明了一种用数学方式来描述神经网络的办法,他们把神经系统中的神经元描述成小而简单的自动控制单元。1956 年,数学家 Stephen Cole Kleene 在他们研究的基础上,发表了一篇名为神经网事件的表示法的论文,在其中,他采用了一些称之为“正则集合(regular set)”的数学符号来描述神经网络模型。之后,UNIX 的主要发明人 Ken Thompson 将这个符号系统引入了文本编辑器 QED(意思是“在文本中搜索某种模式”),正则表达式由此也进入了计算机世界。随后 Ken Thompson 又将正则表达式引入了 UNIX 下的文本编辑器 ed,ed 最终演化为大家熟悉的 grep(grep 得名自 ed 编辑器中的正则表达式搜索命令 g/re/p,其中的 re 表示“正则表达式”)。VI 返璞归真评正则指引 返璞归真评正则指引 第一次接触正则表达式,是 2000 年我在西安一家公司使用 Perl 做网站开发时。之前我在工作中只使用过标准的 C 语言,Perl 这门编程语言的强大表达能力,令我印象极为深刻。Perl 的力量,除了语言本身的设计之外,很大程度上来自它对正则表达式的完美支持。当时我们开发了一个网上商城的应用,允许很多商家在这里开店,可以选择一些不同的样式模板。我很快发现,使用 Perl+正则表达式是开发这类应用的利器。我们只花了大约一个月的时间,就完成了网站核心功能的开发。那时候我意识到,使用正则表达式是聪明人写程序的方法(没说我是聪明人,但是我非常希望与那些聪明人为伍),可以极大地提高代码的重用度和执行效率。如果完全不使用正则表达式,代码量会增加数倍甚至数十倍。后来因为一些原因,我告别了 Perl。在之后的工作中,我使用过 Java、JavaScript、Ruby 等编程语言。我发现这些语言对于正则表达式的支持,没有一个能够超越 Perl。Java 这种所谓的“工业主流编程语言”,一直到 2002 年 JDK 1.4 推出时,才正式把对正则表达式的支持加入核心类库。因为长期缺乏对正则表达式的原生支持,以及语言本身表达能力欠缺,使用 Java 来做大量的文本处理,感觉非常笨拙,完全没有使用 Perl 那种指哪打哪的快感。直到 2007 年我发现了另一个更好的 Perl 语言Ruby,才重新找回了 2000 年 Perl 带给我的编程快感。因为我的工作主要是做 Web 开发,大量的时间花在与 HTML/CSS/JavaScript 以及关系数据库打交道上。在这里并没有很高深的算法,只有大量繁重的文本处理。难以想象,如果没有正则表达式,我们的开发将会是何等原始。除了 Web 开发领域,需要实现大量自动化功能的一些领域,例如运维领域和自动化测试领域,也是正则表达式大显身手的地方。无论使用稍显简陋的 sed/awk 还是更高级的 Perl/Python/Ruby,实现自动化功能,都必须依赖大量的正则表达式。自从面向对象的编辑方式时髦起来之后,甚至一度出现了面向对象万能论,有人试图用 MDA和可执行的 UML 来解决一切编程问题。但是我一直认为面向对象只解决了软件开发的一小部分问题,而且是宏观方面的问题。正则表达式解决的问题,是面向对象无能为力的一些微观方面的问题。在这里不需要坐而论道的方法论争论,需要的是刺刀见红的肉搏战。这些问题即使使用完全面向对象的方式能够解决,也会是很笨拙的。如果用物理学来比喻,面向对象是“广义相对论”,返璞归真评正则指引 VII 而正则表达式则是“量子力学”。正则表达式已经成为现代编程语言的基础模块,现在很难找到一种不支持正则表达式的编程语言。除了编程语言外,在很多工具软件,例如文本编辑器(Vi、Emacs、UltraEdit)、Web 服务器(Apache、Nginx)中都能找到正则表达式的身影。余晟老师是我的朋友,我对他印象最为深刻的是他对于技术工作的严谨态度。“格物致知”是中国传统儒家学派所追求的一种道德修养,也是一种境界。余老师是我的朋友中最接近“格物致知”这种境界的一位。我虽然从未精通过任何一门技术,但是很喜欢结交余老师这样的朋友。余老师潜心编著的这本正则指引深入浅出,将正则表达式的由来和分支娓娓道来。阅读这本书,我仿佛回到了 11 年前