我正在寻找一个正则表达式来匹配对可变参数 c 函数的所有潜在多行调用。最终目标是打印文件、行号和每次调用的第四个参数,但不幸的是我还没有做到这一点。到目前为止,我有这个:
perl -ne 'print if s/^.*?(func1\s*\(([^\)\(,]+||,|\((?2)\))*\)).*?$/$1/s' test.c
与测试.c:
int main() {
func1( a, b, c, d);
func1( a, b,
c, d);
func1( func2(), b, c, d, e );
func1( func2(a), b, c, d, e );
return 1;
}
——与第二次调用不匹配。它不匹配的原因是表达式末尾的 s
允许 .
匹配换行符,但似乎不允许 [.. ]
构造以匹配换行符。我不知道如何克服这个问题。
我也不确定如何引用此中的第四个参数... $2
、$3
不会在此填充(即使它们填充了)我想由于正则表达式的递归性质,我会遇到一些问题。
最佳答案
这应该能捕获你的函数,但有警告
perl -0777 -wnE'@f = /(func1\s*\( [^;]* \))\s*;/xg; s/\s+/ /g, say for @f' tt.c
我使用的事实是语句必须以 ;
终止。然后,这排除了注释中意外的 ;
,并且排除了嵌套在另一个调用中的对此的调用。如果这是可能的,那么需要做更多的工作来解析它。
然而,进一步解析捕获的调用(可能是通过逗号)会变得复杂,因为嵌套调用实际上很可能包含逗号。怎么样
func1( a, b, f2(a2, b2), c, f3(a3, b3), d );
这成为一个更有趣的小解析问题。或者,宏怎么样?
您能澄清一下哪些事情是人们不需要考虑的吗?
由于提到的警告可能会被忽略,这里有一种解析参数列表的方法,使用 Text::Balanced .
由于我们需要提取整个函数调用(如果它们作为参数出现),例如 f(a, b)
,因此库中最合适的函数是 extract_tagged
。有了它,我们可以将开始标记设为单词左括号 (\w+\(
),将结束标记设为右括号 \)
。
此函数仅提取第一个匹配项,因此将其包装在 extract_multiple
use warnings;
use strict;
use feature 'say';
use Text::Balanced qw(extract_multiple extract_tagged);
use Path::Tiny; # path(). for slurp
my $file = shift // die "Usage: $0 file-to-parse\n";
my @functions = path($file)->slurp =~ /( func1\( [^;]* \) );/xg;
s/\s+/ /g for @functions;
for my $func (@functions) {
my ($args) = $func =~ /func1\s*\(\s* (.*) \s*\)/x;
say $args;
my @parts = extract_multiple( $args, [ sub {
extract_tagged($args, '\\w+\\(', '\\\)', '.*?(?=\w+\()')
} ] );
my @arguments = grep { /\S/ } map { /\(/ ? $_ : split /\s*,\s*/ } @parts;
s/^\s*|\s*\z//g for @arguments;
say "\t$_" for @arguments;
}
extract_multiple
返回仅包含(嵌套)函数调用的部分(可通过括号来识别),这些部分是它们本身的参数,也是我们通过所有这些寻求的内容,以及带有逗号的字符串部分- 分隔的其他参数组,这些参数被分成单独的参数。
注意 extract_tagged
中的转义量(通过反复试验发现)!这是必需的,因为这些字符串在字符串 eval 中被两次双引号引起来。这根本没有记录,所以请参阅 the source (例如here)。
或者直接生成需要转义的字符(\x5C
for \
),然后不需要转义
extract_tagged($_[0], "\x5C".'w+'."\x5C(", '\x5C)', '.*?(?=\w+\()')
我不知道我会称之为“更清晰”
我对问题中提供的文件进行了测试,并向其中添加了一个函数
func1( a, b, f2(a2, f3(a3, b3), b2), c, f4(a4, b4), d, e );
对于每个函数,程序都会打印带有要解析的参数列表和解析后的参数的字符串,输出中最有趣的部分是上述(添加的)函数
[ ... ] a, b, f2(a2, f3(a3, b3), b2), c, f4(a4, b4), d, e a b f2(a2, f3(a3, b3), b2) c f4(a4, b4) d e
关于regex - perl 正则表达式用于匹配对 c 函数的多行调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73376526/