1
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
4

3 回答 3

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";
}
于 2013-10-08T14:57:38.260 回答
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";
  }
于 2013-10-08T14:04:38.627 回答
1

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


my @arr = map /(\w+)$/, split /\W*?,\W*/, $arg;
应该是这样
my @arr = map /(\w+)\W*$/, split /\W*?,\W*/, $arg;
,因为 split 中的最后一个元素得到了残留字符。

一旦你掌握了 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";
 }
于 2013-10-08T16:59:53.270 回答