2010-04-14 73 views
1

我正在运行读取文件的代码,执行一些解析,但需要忽略所有注释。 有很好的解释如何进行呢,像答案How can I strip multiline C comments from a file using Perl?当我使用Perl处理C源文件时,如何忽略C注释?

$/ = undef; 
$_ = <>; 
s#/\*[^*]*\*+([^/*][^*]*\*+)*/|("(\\.|[^"\\])*"|'(\\.|[^'\\])*'|.[^/"'\\]*)#defined $2 ? $2 : ""#gse; 
print; 

我的第一个问题是,运行此行$/ = undef;我的代码不能正常工作了。其实,我不知道它做了什么。但如果我忽略了所有评论后可以将其返回,这将会有所帮助。

一般来说,在不更改代码的其余部分的情况下忽略所有注释的有效方法是什么?

+0

也见http://stackoverflow.com/questions/2578671/where-can-i-find-information-about-perls-special-变量 – 2010-04-14 15:27:15

回答

1

你想使$/地方,如在

$_ = do { local $/; <> }; 

{ 
    local $/; 
    $_ = <>; 
    #... 
} 

或者,你可以使用File::Slurp

2

AWK

$ cat file.c 
one 
two 
three // comment at the back 
// comment in front 
four /* another comment */ 
/* comment spanning 
    multiple 
    lines 
*/ five 
six 
seven 

$ awk -vRS='*/' '{ gsub(/\/\*.*/,"");gsub("//.*","")}1' file.c 
one 
two 
three 


    five 
six 
seven 

awk命令设置记录分隔RS*/,这对于多线样式注释结束标记。因此它会重复记录,检查/*(开始标记),然后获取/*前面的任何内容。这个概念很简单,你不必为此制作复杂的正则表达式。类似的,如果你使用Python这样做,

>>> data=open("file").read() 
>>> for item in data.split("*/"): 
...  if "//" in item: item=item.split("//")[0] 
...  if "/*" in item: item=item.split("/*")[0] 
...  print item 
... 
one 
two 
three 


    five 
six 
seven 
1

如果您正在剥离“嵌套”的意见,即:

/* This is a comment 
/* that has been re-commented */ possibly /* due to */ 
various modifications */ 

正则表达式可能不是最好的解决办法。特别是如果这样跨越多行,如上面的例子。

上次我不得不做这样的事情,我一次只读一行,保留“/ *”级别(或者特定语言的任何分隔符)并且不打印任何东西除非计数为0

这是一个例子 - 我提前道歉,因为这是非常糟糕的Perl,但是,至少这应该给你一个想法:

use strict; 

my $infile = $ARGV[0]; # File name 

# Slurp up input file in an array 
open (FH, "< $infile") or die "Opening: $infile"; 
my @INPUT_ARRAY = <FH>; 
my @ARRAY; 
my ($i,$j); 
my $line; 


# Removes all kind of comments (single-line, multi-line, nested). 
# Further parsing will be carried on the stripped lines (in @ARRAY) but 
# the error messaging routine will reference the original @INPUT_ARRAY 
# so line fragments may contain comments. 
my $commentLevel = 0; 

for ($i=0; $i < @INPUT_ARRAY; $i++) 
{ 
    my @explodedLine = split(//,$INPUT_ARRAY[$i]); 
    my $resultLine =""; 

    for ($j=0; $j < @explodedLine; $j++) 
    { 
     if ($commentLevel > 0) 
     { 
      $resultLine .= " "; 
     } 
     if ($explodedLine[$j] eq "/" && $explodedLine[($j+1)] eq "*") 
     { 
       $commentLevel++; 
       next; 
     }   
     if ($explodedLine[$j] eq "*" && $explodedLine[($j+1)] eq "/") 
     { 
       $commentLevel--; 
       $j++; 
       next; 
     }  
     if (($commentLevel == 0) || ($explodedLine[$j] eq "\n")) 
     { 
      $resultLine .= $explodedLine[$j]; 
     } 
    } 

$ARRAY[$i]=join(" ",$resultLine); 
} 


close(FH) or die "Closing: $!";