想象一下这幅图景:你需要检索某台Web服务器上的页面中的重复单词(例如“this this”),进行大规模文本编辑时,这是一项常见的任务。你的任务是,给出满足下面条件的办法:
l 检查多个文件,报告包含重复单词的行,高亮标记每个重复单词(使用标准ANSI的转义字符序列(escape sequence)),同时必须显示这行文字来自哪个文件。
l 跨行查找,即使两个单词一个在某行末尾而另一个在下一行的开头,也算重复单词。
l 进行不区分大小写的查找,例如‘The the…’,重复单词之间可以出现任意数量的空白字符(空格符、制表符、换行符之类)(译注1)。
l 查找用HTML tag分隔的重复单词。HTML tag用于标记互联网页上的文本,例如,粗体单词是这样表示的:‘…it is <B>very</B> very important…’。
这些问题并不容易解决,但又不能不解决。我在写作本书的手稿时,曾用一个工具来检查已经写好的部分,我惊奇地发现,其中竟有那么多的重复单词。能够解决这种问题的编程语言有许多,但是用支持正则表达式的语言来处理会相当简单。
正则表达式(Regular Expression)是强大、便捷、高效的文本处理工具。正则表达式本身,加上如同一门袖珍编程语言的通用模式表示法(general pattern notation),赋予使用者描述和分析文本的能力。配合上特定工具提供的额外支持,正则表达式能够添加、删除、分离、叠加、插入和修整各种类型的文本和数据。
正则表达式的使用难度只相当于文本编辑器的搜索命令,但功能却与完整的文本处理语言一样强大。本书将向读者展示正则表达式提高生产率的诸多办法。它会教导读者如何学会用正则表达式来思考(think regular expressions),以便于掌握它们,充分利用它们的强大功能。
如果使用当今流行的程序设计语言,解决重复单词问题的完整程序可能仅仅只需要几行代码。使用一个正则表达式的搜索和替换命令,读者就可以查找文档中的重复单词,并把它们标记为高亮。加上另一个,你可以删除所有不包含重复单词的行(只留下需要在结果中出现的行)。最后,利用第三个正则表达式,你可以确保结果中的所有行都以它所在文件的名字开头。在下一章里,我们会看到用Perl和Java编制的程序。
宿主语言(例如Perl、Java以及VB.NET)提供了外围的处理支持,但是真正的能力来自正则表达式。为了驾驭这种语言,满足自己的需求,读者必须知道如何构建正则表达式,才能识别符合要求的文本,同时忽略不需要的文本。然后,就可以把表达式和语言支持的构建方式结合起来,真正处理这些文本(加入合适的高亮标记代码,删除文本,修改文本,等等)。
解决实际问题
Solving Real Problems
掌握正则表达式,可能带来超乎你之前想象的文本处理能力。每一天,我都依靠正则表达式解决各种大大小小的问题(通常的情况是,问题本身并不复杂,但没有正则表达式就成了大问题)。
要说明正则表达式的价值,可以举一个用正则表达式解决大而重要的问题的例子,但是它不一定能代表正则表达式在平时解决的那些“不值一提”(uninteresting)的问题。这里的“不值一提”是指这类问题并不能成为谈资,可是不解决它们,你就没法继续干活。
举个简单的例子,我需要检查许多文件(事实上,本书的手稿存放在70个文件中),确保每一行中‘SetSize’出现的次数与‘ResetSize’的一样多。为了应付复杂的情况,我还需要考虑大小写的情况(举例来说,‘setSIZE’也算做‘SetSize’)。人工检查32 000行文字显然不现实。
即便使用文本编辑器的“单词查找”功能,也不够方便,尤其是对所有文件进行同样的操作,何况还需要考虑所有可能的大小写情况。
正则表达式就是解决这个问题的灵丹妙药。只需要一个简单的命令,我就能够检查所有的文件,获得我需要知道的结果。时间是:写命令大概15秒,检索所有的数据实际只花了2秒。这真是棒极了(如果您有兴趣知道我是如何做的,不妨现在就翻到第36页)!
再举一个例子,我曾帮助一个朋友处理远端机器上的某些E-mail,他希望我把他邮箱文件中的消息作为列表发送给他。我可以把整个文件导入文本编辑器,手工删除所有信息,只留下邮件头中的几行,作为内容的列表。尽管文件不是很大,连接速度也不算慢,这样的任务还是很耗费时间而且很乏味。而且,窥见他的邮件正文,也令我尴尬。
正则表达式再一次提供了帮助!我用一个简单的命令(使用本章稍后提到的一个常用工具egrep)显示每封邮件的From:和Subject:字段。为了告诉egrep我需要提取哪些行,我使用了正则表达式「^(From|Sbuject):」。
朋友得到这个列表之后,让我找一封特殊的(5 000行!)邮件。使用文本编辑器或者邮件系统来提取一封邮件无疑非常耗时。相反,我借助另一个工具(叫做sed),同样使用正则表达式来描述文件中我需要的内容。这样,我能迅速而方便地提取和发送需要的邮件。
使用正则表达式节省下来的时间或许并不能让人“激动”,但总比把时间消耗在文本编辑器中要好。如果我不知道有正则表达式这种玩意儿,根本就不会想到还有别的解决办法。所以,这个故事告诉我们,正则表达式和相关的工具能够让我们以可能未曾想过的方式来解决问题。
一旦掌握了正则表达式,你就会知道到它简直是工具中的无价之宝,你也难以想象之前那些没有正则表达式的日子是怎么度过的(注1)。
全面掌握正则表达式是很有用的。本书提供了掌握这种技能所需要的信息,我同时也希望,这本书也提供了促使你学习的动机。







