4.7. 字符介绍——写正则表达式
4.7 字符介绍——写正则表达式
对所有实用目的,你可以依赖一个程序来产生正确的结果。然而这并不意味着程序永远像你想象的那样正确工作。大多数时候你可以打赌的是,如果一个程序没有按你期待的那样产生结果,真正的问题(抛开输入或语法错误)是如何描述你想要的东西。
换句话说,纠正问题的地方是描述你想要结果的表达式。表达式可能不完整或表达得不恰当。比如如果一个程序对这个表达式估值:
PAY = WEEKLY_SALARY * 52
知道这些变量的值,它将计算出正确的结果。但是有人可能会反对,这个表达式没有考虑到销售人员,它们还要获得佣金。要描述这个例子,表达式需要修正如下:
PAY = WEEKLY_SALARY * 52 + COMMISSION
你可以说写第一个表达式的人没有完全理解问题的范围,因此没有把它描述好。知道一个描述必须多具体是很重要的。如果你叫一个人给你一本书,面前又有许多本书,你就需要把你要的书描述得更加具体(或者你就只能满足于不确定的选择过程。)
正则表达式也是一样的,像 grep 这种程序很简单,很容易使用。了解正则表达式的元素也不是很难。重的表达是让你写简单或者复杂的描述或模式。然而,让写正则表达式困难(和有趣)的,正是应用的复杂性:模式出现的各种情况或上下文。复杂性是固有在语言本身的。就像不能总是通过在字典里查每个单词的意思,去理解一个习语的意思。
写正则表达式的过程包括三个步骤:
- 知道你想要匹配的是什么,然后它可能在文本中怎如何出现。
- 写一个描述你想要匹配什么的模式。
- 测试这个模式,看它匹配了什么。
这个过程几乎和一个程序员开发一个程序的过程是一样的。第一步可以被认为是规范,它应该反应要解决的问题和如何去解决它的理解。第二步类似于实际的代码编写。第三步包含运行程序,按规范对它进行测试。第二步和第三步形成一个反复地循环,直到这个程序让人满意工作为止。
测试你想要匹配什么的描述,确保这个描述按你需要的那样工作。通常会发现一些意外。小心地检查一个测试的结果,比较输出和输入,将大大提升你对正则表达式的理解。你可以按下面的方式评估一个模式匹配—操作的结果:
Hits
想要匹配的行。
Misses
不想匹配的行。
Omissions
没有匹配上但想匹配的行
False alarms
匹配上的但不想匹配的行。
你从两端来完善你对一个模式的描述:通过限制可能的匹配来消除 False alarms,通过扩展可能的匹配来捕获 omissions。
当你必须描述使用固定字符串的模式时,这个困难就更加明显。你从固定字符串模式中移除的每一个字符都会增加可能匹配的数量。比如当搜索一个字符串 “what,”,你还想要匹配大写的 “What” 。唯一匹配 “What”和“what” 的固定字符串是 “hat,” 这是它们两个最长的相同的字符串。然而很明显,搜索 “hat” 将会产生不想要的匹配。你加到一个固定字符串模式中的每一个字符都会减少可能匹配的数量。字符串 “them‘” 通常将产生比字符串 “the.” 更少的匹配。
在模式中使用元字符会更加灵活的扩展和收缩匹配范围。元字符和字面量以及其它元字符一起结合使用,能被用来扩展匹配范围,同时还能够消除你不想要的匹配。