vlambda博客
学习文章列表

芯片开发必备工具 | 正则表达式(RegularExpression)使用指南

在芯片开发过程中,正则表达式的使用非常常见。初次上手晦涩难懂,多用几次爱不释手!


芯片开发必备工具 | 正则表达式(RegularExpression)使用指南

01 正则表达式概述


正则表达式,Regular Expression,或缩写regexp,是一种用于描述文本模式(pattern)的表达式。通过该文本模式,我们可以从文本中高效和准确地匹配查找到想要的字符串。

正则表达式的搜索和匹配功能非常强大,以至于几乎所有的脚本语言(比如Python, Perl,JavaScript),Java等高级编程语言,甚至grep等一些Linux命令,都支持正则表达式。

在芯片开发过程中,难免会有很多胶水脚本(glue script)用来串接各种流程,也就不可避免的需要对流程中产生的中间文件做处理,可能是提取、删除或者修改内容等等。另外,在代码review、仿真调试等阶段,通常需要对代码或者仿真日志做信息检索或数据有效性检查

而这些,都是正则表达式在芯片开发过程中大显身手的地方。


芯片开发必备工具 | 正则表达式(RegularExpression)使用指南

02 Cheat Sheet


CheatSheet可作为日常工具手册,用户可以快速地查阅正则表达式的匹配规则。不过,实际经验告诉我,多用了几次之后,常用的匹配规则也就都记住了。

芯片开发必备工具 | 正则表达式(RegularExpression)使用指南


芯片开发必备工具 | 正则表达式(RegularExpression)使用指南

03 常用关系特性


从CheatSheet可以直接看到正则表达式最基础的匹配规则,包括匹配数字、字母、空白、通配符、开头、结尾等等。但在实际使用中,还需要考虑一些匹配关系,这也是本小节想要呈现的内容。

> 捕获分组(capturing group)和非捕获分组(non-capturing group)

在正则表达式中,可以使用圆括号对表达式进行分组。在匹配完成后,就可以使用分组编号来对圆括号中的内容进行提取。默认情况下,整个表达式的分组编号是0,之后从左往右每遇到一个”(”就分配一个递增的分组编号。举个栗子:

芯片开发必备工具 | 正则表达式(RegularExpression)使用指南

除了如上图所示直接使用分组编号对匹配结果进行索引,我们还可以在表达式内进行分组命名,这样就可以是使用组名来进行索引。举个栗子:

芯片开发必备工具 | 正则表达式(RegularExpression)使用指南

非捕获分组同样使用小括号来进行匹配,其格式是(?:exp)。非捕获分组只能在当前的位置匹配文本,不会被分配分组编号,也即是说,在匹配完成之后无法通过分组编号对其进行索引。

> 前向匹配(lookahead)和后向匹配(lookbehind)

前向匹配和后向匹配,严格来讲也是非捕获分组。在有些地方会叫做环视(lookaround),意味着在匹配的时候需要先“环顾四周”。前后向匹配在实际应用中非常常用。

前向匹配(?=exp),用来匹配右边跟着指定字符串的文本;后向匹配(?<=exp),用来匹配左边跟着指定字符串的文本。举个栗子,匹配2022年且日期为22号的月份:

芯片开发必备工具 | 正则表达式(RegularExpression)使用指南

相反,通过把前后匹配表达式中的”=“改成”!”,即(?<!exp)和(?!exp),可以分别匹配左右两边不是指定字符串的文本。

> 贪婪匹配(greedy)和非贪婪匹配(non-greedy)

贪婪程度指的是正则表达式匹配停止的条件,贪婪模式会尽可能多的匹配,非贪婪模式会尽可能少的匹配。

默认的匹配模式是贪婪模式,举个栗子:\d+可以匹配大于1个数字的字符串,那么针对被检索文本“20220122”,正则表达式默认尽可能多的匹配,即匹配整个“20220122”,因为它都满足“大于1个数字的字符串”这个pattern,而不是只匹配第一个数字“2”或匹配部分数字“20220”。

非贪婪匹配也是非常常用的匹配模式,有些地方会叫做懒惰匹配(lazy),但都是一个意思:通过添加?来改变正则表达式匹配停止的条件。举个栗子:


04 测试工具


这里推荐正则表达式的在线测试工具:https://regexr.com/ 在该网站上,提供了正则表达式的使用参考,并且可以供用户测试自己写出来的正则表达式是否符合预期