1、正则表达式入门
正则表达式,是文本处理方面功能最强大的工具之一。
正则表达式语言,用来构造正则表达式(最终构造出来的字符串就称为正则表达式),最终用来完成文本的搜索和替换操作。
1.1 正则表达式的用途
和其他工具一样,正则表达式是人们为了解决特定的问题而发明的一种工具。要想理解正则表达式及其功用,最好的办法是了解它可以解决什么样的问题。
请考虑以下几个场景:
你正在搜索一个文件,这个文件里包含单词car(不区分字母大小写),但你并不想把包含字符串car的其他单词(比如scar、carry和incarcerate等)也找出来。
你打算生成一个网页以显示从某个数据库里检索出来的文本。在那些文本里可能包含一些URL地址字符串,而你希望那些URL地址在最终生成的页面里是可点击的(也就是说,你打算生成一些合法的HTML代码————而不仅仅是普通的文本)。
你创建了一个包含一张表单的应用程序,这个应用程序负责收集包括电子邮件地址在内的用户信息。你需要检查用户给出的电子邮件地址是否符合正确的语法格式。
你正在编辑一段源代码并且要把所有的size都替换为isize,但这种替换仅限于单词size本身,并不涉及那些包含字符串size的其他单词。
你正在显示一份计算机文件系统中所有文件的清单,但你只想把文件名里包含Application字样的文件列举出来。
你正在把一些数据导入应用程序。那些数据以制表符作为分隔符,但你的应用程序要支持CSV格式(每条记录独占一行,同一条记录里的各项数据之间用逗号分隔,数据允许出现在引号内)。
你需要在文件里搜索某个特定的文本,但你只想把出现在特定位置(比如每行的开头或是每条语句的结尾)的文本找出来。
以上场景是大家在编写程序时经常会遇到的问题,用任何一种支持条件处理和字符串操作的编程语言都可以解决,但问题是这种解决方案会变得十分复杂。比较容易想到的办法是,用一些循环来依次遍历那些单词或字符并在循环体里面用一系列if语句来进行测试,这往往意味着你需要使用大量的标志来记录已经找到了什么、还没有找到什么,另外少不了要检查空白字符和特殊字符,等等。而这一切都需要一遍又一遍地以手工方式进行。
另一种解决方案是使用正则表达式。上述问题都可以用一些精心构造的语句,或者说一些由文本和特殊指令构成的高度简练的字符串来解决,比如像下面这样的语句:
\b[Cc][Aa][Rr]\b
1.2 如何使用正则表达式
如果认真思考一下那些问题场景,就会发现它们不外乎两种情况:
一种是查找特定的信息(搜索),另一种是查找并编辑特定的信息(替换)。
事实上,从根本上来讲,这正是正则表达式的两种基本用途:搜索和替换。给定一个正则表达式,它要么匹配一些文本(进行一次搜索),要么匹配并替换一些文本(进行一次替换)。
1.2.1 用正则表达式进行搜索
正则表达式的主要用途之一,是搜索变化多端的文本,比如刚才描述的搜索单词car的场景:
你要把car、CAR、Car和CaR都找出来,但这只是整个问题中比较简单的一部分(有许多搜索工具都可以完成不区分字母大小写的搜索)。
比较困难的部分是确保scar、carry和incarcerate之类的单词不会被匹配到。
一些比较高级的编辑器提供了“Match Only Whole Word(仅匹配整个单词)”选项,但还有许多编辑器并不具备这一功能,而你往往无法在正在编辑的文档里做出这种调整。使用正则表达式而不是文本car进行搜索就可以解决这个问题。
提示 想知道如何解决这个问题吗?你其实已经见过答案了,它就是我们刚才给出的示例语句:\b[Cc][Aa][Rr]\b。
请注意,“相等”(equality)测试(比如说,用户给出的电子邮件地址是否匹配这个正则表达式)本质上也是一种搜索操作,这种搜索操作会对用户所提供的整个字符串进行搜索以寻找一个匹配。与此相对的是子串搜索,这是搜索的惯常含义。
1.2.2 用正则表达式进行替换
正则表达式搜索的威力极其强大,非常实用,而且比较容易学习和掌握。本书的许多章节和示例都与“匹配”有关。
不过,正则表达式的真正威力,体现在替换操作方面,比如我们刚才所描述的把URL地址字符串替换为可点击URL地址的场景:这需要先把相关文本里的URL地址字符串找出来(比如说,通过搜索以http://或https://开头并以句号、逗号或空白字符结尾的字符串),再把找到的URL地址字符串替换为HTML的<a href=...> ... </a>元素,如下所示:
http://www.forta.com/
替换结果:
<a href="http://www.forta.com">http://www.forta.com/</a>
绝大多数应用程序的“Search and Replace(搜索和替换)”选项都可以实现这种替换操作,但使用正则表达式来完成这个任务将简单得让人难以置信。
1.3 什么是正则表达式
现在,你已经知道正则表达式是用来干什么的了,我们再来给它下个定义。
简单地说,正则表达式,是一些用来匹配和处理文本的字符串。
正则表达式,是用正则表达式语言创建的。这种语言专门就是为了解决我们前面所描述的种种问题的。与其他程序设计语言一样,正则表达式语言也有必须要学习的特殊语法和指令,这正是本书要教给大家的东西。
正则表达式语言并不是一种完备的程序设计语言,它甚至算不上是一种能够直接安装并运行的程序或实用工具。更准确地说,正则表达式语言是内置于其他语言或软件产品里的“迷你”语言。好在现在几乎所有的语言或工具都支持正则表达式,但是正则表达式与你正在使用的语言或工具可以说毫无相似之处。正则表达式语言虽然也被称为一种语言,但它与人们对语言的印象相去甚远。
注意 正则表达式起源于20世纪50年代在数学领域的一些研究工作。几年之后,计算机领域借鉴那些研究工作的成果和思路开发出了Unix世界里的Perl语言和grep等实用工具。多年间,正则表达式仅限于Unix社群(用于解决我们前面所描述的各种问题),但这种情况如今已发生了变化,现在几乎所有的计算平台都以不同的形式对正则表达式提供了支持。
说完这些掌故,我们再来看几个例子。下面都是合法的正则表达式(稍后再解释它们的用途):
Ben
.
www\.forta\.com
[a-zA-Z0-9_.]*
<[Hh]1>.*
\r\n\r\n
\d{3,3}-\d{3,3}-\d{4,4}
请注意,语法是正则表达式最容易掌握的部分,真正的挑战在于如何运用语法,如何把实际问题分解为可由正则表达式解决的子问题。与学习其他程序设计语言一样,只靠读书是学不会正则表达式的,实践出真知。
1.4 使用正则表达式
正如前面解释的那样,不存在所谓的正则表达式程序。它既不是可以直接运行的应用程序,也不是可以从哪里购买或下载下来的软件。在绝大多数的软件产品、编程语言、实用工具和开发环境里,正则表达式语言都已被实现。
正则表达式的使用方法和具体功能,在不同的应用程序/语言中各有不同。一般来说,应用程序大多通过菜单选项和对话框来使用正则表达式,而程序设计语言大都通过函数、类或对象提供正则表达式功能。
此外,并非所有的正则表达式实现都是一样的。在不同的应用程序/语言里,正则表达式的语法和功能也会有些许差异。
附录A对支持正则表达式的许多应用程序和语言在这方面的细节进行了汇总。在继续学习下一章之前,你应该先熟悉一下附录A,看看你正在使用的应用程序或语言在正则表达式方面都有哪些与众不同之处。
为了帮助大家尽快入门,我们在这本书的配套网页Learning Regular Expressions – Ben Forta1上准备了正则表达式在线测试工具软件供大家下载。这些在线工具是测试正则表达式的最简单的方法。
1本书中文版见图灵社区本书主页,欢迎读者提交反馈意见和勘误。
1.5 在继续学习之前
在继续学习之前,你还应该了解以下几个事实。
在使用正则表达式的时候,你会发现几乎所有的问题都有不止一种解决方案。有的比较简单,有的比较快速,有的兼容性更好,有的功能更全。
这么说吧,在编写正则表达式的时候,只有对、错两种选择的情况是相当少见的——同一个问题往往会有多种解决方案。
正如前面讲过的那样,正则表达式的不同实现往往会有所差异。在编写本书的时候,我们已尽了最大努力来保证各章里的示例能适用于尽可能多的实现,但有些差异和不兼容是无法回避的,我们针对这种情况都尽可能地进行了注明。
与其他程序设计语言一样,学习正则表达式的关键是实践,实践,再实践。
注意 强烈建议大家在学习本书的过程中亲自实践每一个示例。