正则表达式实用技巧
Practical Regex Techniques
现在我们已经掌握了编写正则表达式所需的基本知识,我希望在更复杂的环境中应用这些知识来处理更复杂的问题。每个正则表达式都必须在下面两个方面求得平衡:准确匹配期望匹配的内容,忽略不期望匹配的字符。我们已经看过许多例子都说明,如果应用得当,匹配优先非常有用,但如果不够小心,也可能带来麻烦,在本章我们还将看到许多例子。
NFA引擎还需要平衡另外一个因素:效率,这也是下一章的主题。设计糟糕的正则表达式——即使可以认为没犯错误——也足以让引擎瘫痪。
本章出现的主要是各种实例,我会带领读者循着我的思路去解决各种问题。某些例子或许对读者并没有现实价值,但我仍然推荐读者阅读这些实例。
例如,即使你的工作不涉及HTML,我仍推荐你从处理HTML的实例中吸取知识。原因在于,编写巧妙的正则表达式不仅仅是一种手艺(skill)——而且还是一种艺术(art)。它的教授和学习,不是依靠罗列规则,而是依靠经验,所以,我用这些例子告诉读者,自己在过去的若干年从经验中获得的深刻启示。
当然,读者仍然需要自己掌握这些知识,但是研究本章的例子是个好的起点。
正则表达式的平衡法则
Regex Balancing Act
好的正则表达式必须在这些方面求得平衡:
l 只匹配期望的文本,排除不期望的文本。
l 必须易于控制和理解。
l 如果使用NFA引擎,必须保证效率(如果能够匹配,必须很快地返回匹配结果,如果不能匹配,应该在尽可能短的时间内报告匹配失败)。
这些方面常常是与具体文本相关的。如果我只使用命令行,只需要快速地grep某些东西,可能不会过分关心匹配的准确性,通常也不会花太多精力来调校。我不在乎多花点时间来手工排查,因为我能够迅速地在输出中找到自己需要的内容。但是,如果处理重要的程序,就需要花费时间精力来保证正确性:如果需要,正则表达式也可能很复杂。这些因素都需要权衡。
即使使用同样的程序,效率也是与具体文本相关的。如果是NFA,用「^-(display| geometry|cemap|…|quick24|random|raw)$」之类长长的正则表达式来检验命令行参数的效率就很低,因为多选分支过多,但如果它只用于检验命令行参数(可能只是在程序开始的时候运行若干次),即使所需时间比正常的长100倍也不要紧,因为这时候效率并不是问题。但是,如果要逐行检查很大的文件,低效率的程序运行起来会让你痛苦不堪。





