perl - 从多行函数定义中提取函数参数

时间:2013-10-08 13:53:28

标签: regex perl

eErrorT ChainCtrlInitChains(ChainCtrlT* pChainCtrl,
    char* name,
    int instance)
{
    ....
}
eErrorT ChainCtrlInit(ChainCtrlT* pChainCtrl, void* pOwner)
{
    ....
}

我的代码

open(my $FILE, "< a.c") or die $!;
my @arr = <$FILE>;
foreach(@arr){  
   if ($_ =~ /^ \S+ \s+ \S+ \s* \( (.+?) \) /xsmg) {
      my $arg = $1;
      my @arr = map /(\w+)$/, split /\W*?,\W*/, $arg;
      print my @temp = map "$_\n", @arr
            unless $_ =~ /;\s*$/;
     }
} 

基本上我从函数定义中提取函数参数。

但在这种情况下,我只能提取第二个函数(ChainCtrlInit)的参数而不能提取第一个函数(ChainCtrlinitchains)的参数。

期望的输出

pChainCtrl
name
instance

pChainCtrl
pOwner

输出我正在

pChainCtrl
pOwner

3 个答案:

答案 0 :(得分:4)

你遇到的问题是当你做“foreach”时,块中的$ _继承了数组中的每个元素。 例如,

foreach(@arr)..循环的第一次迭代使用“eErrorT ChainCtrlInitChains(ChainCtrlT * pChainCtrl,\ n”)分配$ _,这样你的正则表达式就会失败。

并且您还使用没有太多用途的临时变量。我已经改进了以下代码:

my $arr = do { local $/; <$FILE> }; #Copy one of the comments above.

#note there's a slight difference in the 'while' regex to your code
while ($arr =~ /^ \S+ \s+ \S+ \s* (\( .+? \)) /xsmg) { 
    my @args = $1 =~ /(\w+)[,)]/g; #This assumes what you want always ends in 
    #a ',' or a ')', hence the gentle modification in the 'while' regex.
    local $" = "\n";
    say "@args";
}

答案 1 :(得分:2)

问题在于您是逐行读取文件,因此正则表达式永远不会扩展到多行 - 如果您加载文件然后使其成为带有嵌入新行的单个字符串,它将起作用

例如快速黑客提供

open(my $FILE, "< a.c") or die $!;
my @arr = <$FILE>;
my $file = join('',@arr);

 my @matches = $file =~ /^ \S+ \s+ \S+ \s* \( (.+?) \) /xsmg;
 foreach (@matches) {
      my $arg = $_;
      my @arr = map /(\w+)$/, split /\W*?,\W*/, $arg;
      print my @temp = map "$_\n", @arr
            unless $_ =~ /;\s*$/;
      print "\n";
  }

答案 2 :(得分:1)

@ Ad-vic,除了@ atleypnorth的解决方案将整个文件篡改成字符串之外,你的split-map语句中可能存在问题。


my @arr = map /(\w+)$/, split /\W*?,\W*/, $arg;
应该是这个 my @arr = map /(\w+)\W*$/, split /\W*?,\W*/, $arg;
因为拆分中的最后一个元素会获得剩余字符。

一旦掌握了Perl,您可以将其简化为 -

 $/ = "";
 open(my $FILE, "< a.c") or die $!;
 my $str = <$FILE>;

 foreach ( $str =~ /^ \S+ \s+ \S+ \s* \( (.+?) \) /xsmg ) {
     print map "$_\n", /(\w+) [^\w,]* (?:,|$)/xg ;
     print "\n";
 }