python正则


一、公共基础符号(出现在多个模式中)

符号 名称 作用 示例
\b 单词边界 匹配一个位置,该位置一侧是单词字符(\w),另一侧不是。保证匹配完整的单词,不会匹配 inputwire 中的 input \binput\b 匹配 " input" 但不匹配 "inputwire""iinput wire"
\s 空白字符 匹配任意空白符(空格、制表符、换行等) \s+ 匹配一个或多个空白
\w 单词字符 匹配 [A-Za-z0-9_] \w+ 匹配 "clk_100"
+ 量词(一次或多次) 修饰前面的原子,表示至少出现1次 \s+ 至少一个空白
? 量词(零次或一次) 修饰前面的原子,表示出现0次或1次(即可选) \s+? 懒惰匹配(但这里是非贪婪)
* 量词(零次或多次) 修饰前面的原子,表示可以出现任意次(包括0次) \s* 零个或多个空白
[ ] 字符类 匹配方括号内列举的任意一个字符 [^\]] 匹配除了 ] 以外的任意字符
^ 取反(在字符类开头) 在字符类 [^...] 中表示否定,匹配不在括号内的字符 [^\]] 匹配不是 ] 的字符
\ 转义 将特殊字符转义为字面意义,或者引入特殊序列 \] 匹配字面右方括号
( ) 捕获分组 将括号内的表达式作为一个组,并且捕获匹配的文本,供后续提取或反向引用 (\w+) 捕获端口名
(?: ) 非捕获分组 仅用于分组或应用量词,不捕获文本,不保存到结果中 (?:\s*,\s*(\w+)) 整体作为一个组,但不捕获
` ` 分隔两个子表达式,匹配其中任意一个

二、针对每个模式的具体解释

2. pattern2 = r'\binput\s+\w+\s+(\w+)'

符号序列 详细解释(包含“后面有无空格”的影响)
\binput \b 是单词边界位置,只要求 input 前面是边界(行首/空格/标点),不关心后面;input 后面有无空格不影响本段匹配,但若后面紧接字母(如 inputwire),则后续 \s+ 会失败
\s+ 匹配至少一个空白字符(空格/制表符);后面必须紧跟空白,若 input 后面无空白(如直接换行或字母),则整个匹配失败;若有多个空白,\s+ 会全部消耗掉
\w+ 匹配至少一个单词字符(字母/数字/下划线);后面有无空格取决于下一个符号:若下一个是 \s+,则 \w+ 后面必须有空白才能继续;若下一个是其他(如 $),则无空格也可;此处 \w+ 后面是 \s+,所以 \w+ 后面必须紧跟空白才能匹配成功
\s+ 同上,要求前一个 \w+(类型关键字)后面必须有至少一个空白,否则匹配失败
(\w+) 捕获端口名;后面有无空格不影响本捕获组的匹配(因为它是最后一个元素),但如果后面还有字符(如逗号或换行),则不会影响已经捕获的内容;注意:若端口名后面直接跟非空白字符(如 clk,),则 \w+ 会匹配 clk 而停止于逗号,因为逗号不是单词字符

补充说明

  • \s+ 后面有无空格\s+ 本身消耗空白,它后面如果紧跟 \w+,则中间不需要额外空格,因为 \s+ 已经处理了所有空白。
  • \w+ 后面有无空格:取决于下一个正则原子。若下一个原子是 \s+,则 \w+ 后面必须有空白;若下一个原子是 \b$[ 等,则后面可能没有空白。
  • \b 后面有无空格\b 不消耗字符,所以 \binput\b 后面直接是 i,没有空格问题。但 input\b 要求 t 后面是边界,此时空格是边界的一种,所以 input 后面有空格时 \b 成立,无空格但跟字母时 \b 不成立。

整体作用:匹配不带位宽的输入端口,返回端口名。


3. pattern3 = r'\binput\s+\w+\s+(?:(\[[^\]]+\])\s+)?(\w+)'

不必须顶格,前面可以有空格。
原因:正则表达式中的 \b 匹配单词边界。在字符串 " input"(前面有空格)中,空格字符与 i 之间是一个单词边界(因为空格不是单词字符,i 是单词字符),因此 \binput 能够成功匹配。同样,行首、标点符号与 i 之间也是边界。所以 \binput 可以匹配:

  • "input"(行首)
  • " input"(前面有空格)
  • ",input"(前面有逗号)
符号序列 基础符号含义(\b:边界;\s:空白;\w:单词字符;\d:数字;+:一次或多次;?:零或一次;*:零或多次;( ):捕获分组;(?: ):非捕获分组;[ ]:字符类;[^]:否定字符类;|:或;^:行首;$:行尾;.:任意字符(除换行);\[ \]:字面方括号)
\binput\s+\w+\s+ 匹配独立单词input后跟至少一个空白,再跟wire等类型关键字后跟至少一个空白;\s+要求后面必须有空白,若input后无空白或wire后无空白则匹配失败
(?: 开始一个非捕获分组,仅用于将后续的位宽部分组合在一起并设为可选;此分组本身不捕获文本,也不影响后面是否有空格
(\[[^\]]+\]) 捕获组1:匹配方括号及其内部内容(如[31:0]);此原子后面若紧跟\s+则需要有空白,若后面是)则不需要;此处后面是\s+,所以位宽后面必须有空白
\s+ 匹配至少一个空白字符,要求位宽(如果存在)后面必须紧跟空白;若位宽后面无空白(如直接跟端口名),则此\s+匹配失败,导致整个位宽部分无法匹配
)? 结束非捕获分组,?表示整个位宽部分(包括位宽和后面的空白)可以出现0次或1次;若位宽不存在,则直接跳过,不影响后面的端口名匹配
(\w+) 捕获组2:匹配端口名;后面有无空格不影响本捕获(因为它是最后一个元素),但若端口名后面有非单词字符(如逗号或分号),\w+会在单词边界处停止,不会消耗那些字符

关键点说明(原内容未改动):

  • 位宽部分的可选性是通过 (?:...)? 实现的,其中 \s+ 被包含在内,所以如果位宽存在,它后面必须有空白;如果位宽不存在,则不需要空白。
  • 这样设计可以同时匹配 input wire clkinput wire [31:0] clk 两种情况。

4. pattern4 = r'\binput\s+\w+\s+(\w+)(?:\s*,\s*(\w+))*'

这个模式试图匹配一行中多个用逗号分隔的端口名,例如:input wire clk, rst, en

符号序列 解释
\binput\s+\w+\s+ 匹配 input wire
(\w+) 捕获组1:第一个端口名
(?: 开始非捕获分组(用于重复)
\s*,\s* 匹配逗号,两边可有任意空白
(\w+) 捕获组2:后续的端口名
)* 非捕获分组整体可以重复零次或多次

问题findall 只返回最后一个重复捕获组的值(因为正则引擎在重复时只会保留最后一轮捕获的内容)。更可靠的做法是先用 search 提取出 input wire 后面的整个端口列表字符串,再用 split 分割。


三、其他常见但未出现在这些模式中的符号(补充)

符号 名称 作用
^ 行首锚点 匹配字符串的开始(或多行模式下的行首)
$ 行尾锚点 匹配字符串的结束(或多行模式下的行尾)
. 通配符 匹配除换行符外的任意单个字符(默认)
*? +? ?? 懒惰量词 尽可能少地匹配
{n} {n,} {n,m} 精确次数量词 指定重复次数
(?=...) 正向前瞻 要求后面匹配但不消耗字符
(?!...) 负向前瞻 要求后面不匹配
(?<=...) 正向后顾 要求前面匹配
(?<!...) 负向后顾 要求前面不匹配
\1 \2 反向引用 引用前面捕获组的内容

总结

你列出的这些模式已经覆盖了 Verilog 端口解析中最常用的正则技巧:

  • \b 确保单词独立
  • \s+ 处理空白
  • \w+ 匹配标识符
  • \[[^\]]+\] 匹配方括号包围的位宽
  • (?:...) 非捕获分组用于可选或重复
  • ? 使整个位宽部分可选
  • * 重复逗号分隔的端口列表

理解这些符号的作用后,你就能自如地编写或修改正则表达式来适应不同的 Verilog 代码风格了。

posted on 2026-04-15 16:31  泰勒幂级数  阅读(18)  评论(0)    收藏  举报