Perl正则匹配多行C可变参数函数调用的问题求助
解决Perl正则匹配跨多行C可变参数函数调用并提取第四个参数的问题
原正则的问题分析
[^\)\(,]+字符集不匹配换行符,导致跨多行的func1调用无法被捕获;- 递归组写法有误(多余的
||应该改为|); - 没有正确分组来定位并提取第四个参数。
解决方案一:手动解析参数列表(更可靠)
对于带嵌套括号的参数,纯正则拆分容易出问题,手动解析参数列表能更好处理复杂场景,同时支持跨多行匹配:
perl -n -0777 -e ' while (/func1\s*\(\s*(.*?)\s*\)/gs) { my $args = $1; my $count = 0; my $current_arg = ""; my $depth = 0; my $fourth_arg; foreach my $char (split //, $args) { if ($char eq "(") { $depth++ } elsif ($char eq ")") { $depth-- } elsif ($char eq "," && $depth == 0) { $count++; if ($count == 3) { $fourth_arg = ""; } elsif ($count > 3) { last; } $current_arg = ""; next; } $current_arg .= $char if $count >= 3; } if (defined $fourth_arg) { $fourth_arg =~ s/^\s+|\s+$//g; my $line_num = 1 + ($` =~ tr/\n//); print "$ARGV:$line_num: $fourth_arg\n"; } } ' test.c
关键说明:
-0777将整个文件读入内存,避免逐行处理的限制;/func1\s*\(\s*(.*?)\s*\)/gs匹配所有func1调用,s修饰符让.匹配换行,g全局匹配;- 手动遍历参数字符,通过括号深度
$depth区分嵌套括号内的逗号和参数分隔逗号,计数到第四个参数; - 通过统计匹配结果前的换行符数量计算行号,输出文件名、行号和清理后的第四个参数。
测试输出:
test.c:2: d test.c:4: d test.c:5: d test.c:6: d
解决方案二:递归正则提取第四个参数(适合简单场景)
如果你的代码没有注释、字符串内特殊字符等复杂情况,可以用递归正则匹配参数,直接捕获第四个:
perl -n -0777 -e ' my $arg_re = qr/(?:[^(),]+|\((??{$arg_re})\))+/; while (/func1\s*\(\s*(?:$arg_re\s*,\s*){3}($arg_re)/gs) { my $fourth = $1; $fourth =~ s/^\s+|\s+$//g; my $line_num = 1 + ($` =~ tr/\n//); print "$ARGV:$line_num: $fourth\n"; } ' test.c
关键说明:
$arg_re是递归正则,匹配单个参数(包括带嵌套函数调用的参数);(?:$arg_re\s*,\s*){3}匹配前三个参数及后续的逗号和空白;($arg_re)直接捕获第四个参数,后续清理空白并输出位置信息。
内容的提问来源于stack exchange,提问作者HardcoreHenry
相关产品推荐
相关产品推荐

