Perl多行正则匹配故障:无法正确捕获门电路输入网表
问题分析与解决
咱们先拆解下你遇到的问题,你的正则和代码逻辑确实存在几个关键问题,导致没达到预期效果:
核心问题点
- 正则匹配范围偏差:你写的
[A-Z].*?\.[A-C]\d* \( (.*?) \).*?;里,[A-Z].*?是非贪婪匹配,它会从行内第一个大写字母开始,匹配到最近的.A/.B/.C,这就导致你实际匹配到的不是整个门的定义,而是行内中间的某个端口片段(比如你看到的.B ( U_PAUSEwcnt ) ...),自然捕获的内容也不对。 - 对/m修饰符的误解:/m修饰符的作用是让
^匹配每行的开头(包括换行后的行首)、$匹配每行的结尾,不是让.匹配换行(那是/s修饰符的功能)。你的每行都是一个完整的门定义,根本不需要/m。 - 全局匹配的姿势错误:即使加了/g,用
if ($cur_line =~ m/.../g)也只会捕获第一个匹配项。要获取所有匹配,你需要把匹配结果存到数组里,或者用while ($cur_line =~ m/.../g)循环遍历每个匹配。 - 缺少输出网提取与哈希构建逻辑:你的代码完全没处理
.Y端口的提取,也没有把输出网作为键、输入网作为值存入哈希的逻辑。
修正后的代码
下面是调整后的代码,完全实现你想要的功能:
open (FILE, "<maca") or die("Can not open file: $!"); my %gate_output_to_inputs; while (my $cur_line = <FILE>) { chomp $cur_line; # 先提取输出端口.Y对应的网名称,没有输出的行直接跳过 next unless $cur_line =~ /\.Y \( (\w+) \)/; my $output_net = $1; # 全局匹配所有输入端口(排除.Y)的网名称 # 用负向前瞻(?!Y)确保只匹配.A/.B/.C/.A0这类输入端口 my @input_nets = $cur_line =~ /\.(?!Y)[A-Z]\d* \( (\w+) \)/g; # 把输出网作为键,输入网数组的引用作为值存入哈希 $gate_output_to_inputs{$output_net} = \@input_nets; # 打印你想要的格式示例 print "THIS gate $cur_line " . join(' ', @input_nets) . "\n"; } close FILE; # 可选:打印哈希内容验证结果 print "\n=== 最终哈希映射结果 ===\n"; foreach my $out_net (sort keys %gate_output_to_inputs) { my $input_list = join(', ', @{$gate_output_to_inputs{$out_net}}); print "输出网 $out_net -> 输入网列表: $input_list\n"; }
代码说明
- 输出网提取:用
/\.Y \( (\w+) \)/精准捕获.Y后面的网名称,确保只处理有输出的门定义。 - 输入网提取:
/\.(?!Y)[A-Z]\d* \( (\w+) \)/g通过负向前瞻排除.Y,同时全局匹配所有输入端口(支持.A0这类带数字的端口名),把所有输入网存入数组。 - 哈希构建:直接将输出网作为键,输入网数组的引用作为值,完美实现你想要的存储结构。
- 错误处理:把
$file改成$!,这样能打印具体的文件打开错误原因,更便于调试。
用你提供的测试数据运行这段代码,会输出你期望的结果:
THIS gate NAND3_X1R_A9PP96CTUL_C16 SYN_INC_154 ( .A ( n1563 ) , .B ( U_PAUSEwcnt ) , .C ( n1640 ) , .Y ( n1467 ) ) ; n1563 U_PAUSEwcnt n1640 THIS gate AO22_X1N_A9PP96CTS_C24 SYN_INC_187 ( .A0 ( test_so6 ) , .A1 ( n2218 ) , .B0 ( U_PAUSEdata_ff_int_28_ ) , .B1 ( n2 ) , .Y ( n2597 ) ) ; test_so6 n2218 U_PAUSEdata_ff_int_28_ n2
内容的提问来源于stack exchange,提问作者togaclad
相关产品推荐
相关产品推荐

