• 发文
  • 评论
  • 微博
  • 空间
  • 微信

python的正则(一):简单够用的basic版

ExASIC 2020-07-14 14:12 发文

不管是哪种编程语言,学习正则是一节必修课,python也是如此。正则通常被用来做什么?处理复杂的字符串及文本。比如,提取RTL的begin end之间的内容,提取verilog的模块端口完成自动例化,处理APR的io file等。用好正则,常常可以事半功倍。


为了更轻松愉快地学习正则,我们分成三次讲解:

一、特殊字符和基本用法

二、复杂规则

三、一些实例

本文是第一次讲解,介绍正则的特殊字符和基本用法。



温故而知新


回顾一:

在《python的数据类型(三):字符串》中已经介绍过一些字符串的处理函数,先来一起回顾一下,见下图,不记得的同学可以点击链接看看。


回顾二:

与Perl语言的正则对比着学习,可以加深理解和记忆。下面是两篇Perl正则的介绍:

Perl在ASIC中的应用——高级篇(1):Perl的正则表达式

Perl在ASIC中的应用——实战篇(3):网表处理



基本语法介绍


在正则的概念里,有一个术语叫“匹配”,匹配就是利用一些特殊字符如 . * + 等来描述一个字符串。比如有字符串'abbbc',我们可以用'ab+c'来描述。又如verilog的begin end块可以用'begin.*end'来描述。我们可以看到,匹配不仅仅描述某一个字符串,而是描述某一类字符串


与Perl不同,Perl的正则是语言结构的一部分,而Python的正则是定义在模块包re里,使用时需要先import re。


下面,我们先来看看python正则的基本用法,为了简单、容易入门,这次主要介绍与Perl正则语法类似的部分。


特殊字符


. 除外的任意字符
^ 字符串的开头
$ 字符串的结尾
 字符串边界
B 非边界
d 数字0到9
D 非数字
s 空白字符
S 非空白字符
w 字母a-z,A-Z,和下划线_
W 大小写字母和下划线 以外的其它字符
A 字符串开头
Z 字符串结尾

特殊字符前加转义表示字符本身



空白字符


换行符newline 0x0a
制表符tab
回车符0x13
换页符
垂直制表符


字符集合


[...] 字符集合,[]中的特殊字符表示字符本身
[^...] 字符集合以外的字符



分组匹配


| 或,比如A|B,如果A没匹配到,就匹配B



匹配次数(重复次数)


* 重复大于等于0次
+ 重复大于等于1次
? 重复0次或1次



非贪婪模式


*? 
+? 
?? 


默认是贪婪模式,尽可能多的匹配。比如verilog里有很多个begin end块。'begin.*end'是从第一个begin匹配到最后一个end,这往往不是我们想要的。如果我只需要匹配到第一个end,用非贪婪模式'begin.*?end'即可。


1begin
2...
3end
4begin
5...
6end
7begin
8...
9end


引用


(...) 括号中内容可以再后续引用


基本规则介绍完毕。下面介绍几个re模块的函数。




re模块的函数


在Perl中,匹配和替换用下面的语法:



1$str =~ m/.../;
2$str =~ s/.../.../;



re.search


而Python中,由于一切都是对象,我们需要使用re模块中的方法(函数)来实现。在re中有一个search函数,第一个参数是pattern,就是正则,第二个参数是被匹配的字符串。需要注意的是:正则本身也是一个字符串,常使用raw字符串,即r'...',可以避免一些不必要的转义。



1import re
2result = re.search(r'pattern', 'string', option)


如果匹配到了,result.group(0)则是匹配到的字符串;如果没有匹配到,result则为None。所以,可以根据result是不是None来判断是否查找到指定的字符串。例如:


1import re
2s = 'input wire a;input wire b;'
3result = re.search(r'wires+w+;', s)
4print(result.group(0))  # wire a
5if result: # if not result:
6    ...


在正则中加括号()来引用匹配的子字符串,例如下面的一段代码,对verilog信号名a和b加括号,则result.group(1)表示第一个括号匹配的子字符串a,result.group(2)表示第二个括号匹配的子字符串b。而result.group(0)表示匹配的全部字符串。


1import re
2s = 'input wire a;input wire b;'
3result = re.search(r'wires+(w+).*wires(w+)', s, re.S)
4print(result.group(0))  # wire a;input wire b
5print(result.group(1))  # a
6print(result.group(2))  # b


由于原字符串带有换行符,默认.*不能跨越换行符匹配,需要加上re.S的选项才可以。除了re.S还有其它一些常见选项:


re.S    当作单行(Singal line)来匹配

re.M   当作多行(Multi line)来匹配

re.I     忽略(Ignore)大小写


re.sub


正则的主要作用,是进行高级查找和替换,查找是search(),替换就是sub(),如下所示:


1import re
2result = re.sub(r'pattern', r'replace', 'string', count=0, option)


在'string'中查找'pattern',并替换成'replace';

replace为空字符串''时,等同于删除;

count指定替换的次数,默认0是全部替换;

option与search中的相同,可以指定单行、多行、大小写等;

返回值是替换后的新字符串,如果没有匹配到,返回老字符串。


例如,下面的代码,把所有的input替换成output:


1import re
2s = 'input wire a;input wire b;'
3result = re.sub(r'input', r'output', s, 0, re.S)
4print(result) # 'output wire a;output wire b;'


re.findall


因为python中的search()函数不如perl的=~ m/.../灵活,所以re中还提供了其它函数来增强功能,findall()便是其中一个。


顾名思义,findall就是查找所有的匹配,函数返回一个list。语法如下:



1import re
2result = re.findall(r'pattern', 'string', option)


例如,查找所有的输入端口:



1import re
2s = 'input wire a;input wire b;'
3result = re.findall(r'input.*?;', s, re.S)
4print(result) #['input wire a;', 'input wire b;']


我们可以看到,findall()返回了所有输入端口的列表。而search()呢?只返回第一个匹配结果。


re.其它函数


用dir(re)看看re模块包定义了哪些函数,如下:


1import re
2dir(re)
3# [..., 'compile', 'copyreg', 'enum', 'error', 'escape', 
4  'findall', 'finditer', 'fullmatch', 'functools', 'match', 
5  'purge', 'search', 'split', 'sre_compile', 'sre_parse', 
6  'sub', 'subn', 'template']


大家可以用help(re.xxx)来查看帮助。



总结


到此,python正则的基本用法就介绍完毕了。只要我们在实际项目中灵活运用这些基本规则就可以了。


习题:

1. 利用上面介绍的正则基本规则,提取verilog module的端口。

要求:考虑verilog 2001 C风格和和verilog95的传统风格。

2. 把verilog代码中的高电平复位信号rst替换成低电平复位信号rst_n。

提示:除了复位名称需要替换外,always中的复位posedge也需要同时替换成negedge;if(rst)需要替换成 if(!rst_n)。

3. 在第一题的基础上,实现模块实例化。

简化一点,外部连线的名字和端口名相同。



声明:本文为OFweek维科号作者发布,不代表OFweek维科号立场。如有侵权或其他问题,请及时联系我们举报。
2
评论

评论

    相关阅读

    暂无数据

    ExASIC

    分享数字集成电路设计中的经验和方...

    举报文章问题

    ×
    • 营销广告
    • 重复、旧闻
    • 格式问题
    • 低俗
    • 标题夸张
    • 与事实不符
    • 疑似抄袭
    • 我有话要说
    确定 取消

    举报评论问题

    ×
    • 淫秽色情
    • 营销广告
    • 恶意攻击谩骂
    • 我要吐槽
    确定 取消

    用户登录×

    请输入用户名/手机/邮箱

    请输入密码