regex - perl 正则表达式用于匹配对 c 函数的多行调用

标签 regex perl

我正在寻找一个正则表达式来匹配对可变参数 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/

相关文章:

javascript - 如何使用 replace 方法重写 url 路径?

javascript - 口译员和安全口译员有什么区别?

multithreading - perl线程异常退出

Perl:如何指定以 "/"开头的行

perl - HTTP::Request 和文字 %2B

javascript - 威胁模型文档

javascript - 如何用span标签替换特定的文本换行字符?

java - 如何检索字符串中匹配模式的索引?

java - 如何在使用 Split() 函数时避免在 Java 中的字符串开头插入空格

Java - 查找字符串中给定单词之前和之后的单词