所谓正则表达式,就是一种描述字符串结构模式的形式化表达方法,在几乎所有的主流编程语言都获得支持。为什么正则表达式具有如此巨大的魅力?一方面,因为正则表达式处理的对象是字符串,或者抽象地说,是一个对象序列,而这恰恰是当今计算机体系的本质数据结构,我们围绕计算机所做的大多数工作,都归结为在这个序列上操作,因此,正则表达式用途广阔。另一方面,与大多数其他技术不同,正则表达式具有超强的结构描述能力,而在计算机中,正是不同的结构把无差别的字节组织成千差万别的软件对象,再组合成为无所不能的软件系统,因此,描述了结构,就等于描述了系统。在这方面,正则表达式的地位是独特的。正因为这两点,在现在的软件开发和日常数据处理工作中,正则表达式已经成为必不可少的工具。(摘自精通正则表达式)
本文尝试对于正则表达式学习的知识框架,结构和规律进行梳理。具体到每个符号代表什么含义,它具有丰富的变化组合,是一种神奇的魔法,一句正则可以轻松秒杀几百上千行代码,发挥巨大的威力。但正则玩的再六的人也是需要经常翻看速查表的,一般人死记硬背都记不住那些密码一样的东西。核心还是要花时间理解它的构建结构和规律。
顺便推荐几个非常好用的在线工具,rexegg 中也有收集
regex101.com
RegexBuddy
regexper.com
入门
regular expression, 对规则的表达和匹配,既是一种字符匹配的规则也可视为一种编程语言,一种专用于处理字符匹配的语言。核心就是在界定符内做匹配,要么匹配字符,要么匹配位置。匹配到之后可以用于查找,提取,验证,替换,切分文本即字符串。界定符通常由// 或者##标识,界定符右侧紧跟的是装饰符,具体解释参考下图pattern modifier. 匹配字符的又分一般字符,元字符,预定义的字符集;匹配位置的分匹配的个数,边界,再进一步加上各种逻辑和分组,这些构成了正则的底层的基本组件。下面这张图总结的很好,掌握了这张速查表,正则也就算入了门了。
但是,很多人在不同的语言中使用的时候经常会被转义,括号,引号的使用绕晕。这里面除了要理解不同语言本身对于符号如何解析还需要理解正则表达式的流派。目前主要有两大流派,POSIX和PCRE。
POSIX是一系列规范,定义了UNIX 操作系统应当支持的功能,其中也包括正则表达式规范,Vim, Sed, Awk, Grep 遵循这一流派
PCRE,正则在Perl 语言中深度集成,发展出自己的一套规则PCRE,大部分主流的编程语言常见的正则表达式语法都是基于这一流派
细分下去,其实不同的语言,不同操作系统,不同版本还有兼容性的问题和细微的差异,但是在初期阶段可以简单的记住这两种流派并了解其差别。
至此,你应该可以构建和使用一些常见的regex pattern 了,譬如,匹配日期,匹配身份证号码,验证密码是否符合规范,验证输入是否符合要求等等。common pattern 在RegexBuddy 社区由用户上传和维护,可以直接输入关键字search,供参考。
基于我们一贯提倡的不要重复造轮子原则,ICer 常用的regex pattern 在企业级或者CAD framework 级应该被管理起来,应用场景可以被抽象和归类。如何实现,这是一个比较大的话题,可以单独说。
大部分ICer 写脚本会本着能work 就行的原则,不太考虑效率优化,封装抽象,复用等问题,这导致协作效率,代码效率,延展性,可维护性都比较差。我们希望可以为大家提供一个更简单通用的解决方案,感兴趣的可以关注后续文章,这个其实更符合文章题目的本意,轻松玩转正则表达式:-)
进阶
规则是类似的,但是不同的语言中用到不同的正则引擎和工作原理,基于不同的原理构建正则表达式的方式决定了某个正则表达式能否匹配一个字符串,在何处匹配以及匹配成功和失败返回结果的速度。
正则表达式引擎主要有两类,非确定性有限自动机(NFA)引擎(如Perl, Python, Emacs所用的引擎),确定性有限自动机(DFA)引擎(如 awk,egrep,MySql)。
两者的区别在于,NFA是表达式主导,表达式由独立的子表达式构成,完成整个匹配的策略由更上层的逻辑和层级运算来控制,默认使用贪婪匹配,在成功匹配到子表达式时,会保存状态,如果匹配失败会返回到保存的状态继续尝试下面的匹配项,这个过程称为回溯;DFA是字符串主导,遵循最左最长原则,每个字符最多只匹配一遍,无论成功还是失败,没有子表达式,不支持回溯,好处是简单快速。前者以牺牲效率换灵活性,所以在更high level 需要靠程序员的智慧来控制回溯,以补偿牺牲的效率。
领取专属 10元无门槛券
私享最新 技术干货