【问题标题】:How can I ignore C comments when I process a C source file with Perl?使用 Perl 处理 C 源文件时如何忽略 C 注释?
【发布时间】:2011-02-07 19:26:44
【问题描述】:

我正在运行一个读取文件的代码,进行一些解析,但需要忽略所有 cmets。 有很好的解释如何进行,比如How can I strip multiline C comments from a file using Perl?的答案

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

我的第一个问题是,在运行$/ = undef; 这一行之后,我的代码无法正常工作。 其实,我不知道它是做什么的。但是,如果我可以在忽略所有 cmets 后将其转回,那将会很有帮助。

一般来说,在不更改其余代码的情况下忽略所有 cmets 的有用方法是什么?

【问题讨论】:

标签: perl


【解决方案1】:

如果您要剥离“嵌套”的 cmets,即:

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

regexp 可能不是最好的解决方案。尤其是如果它像上面的示例那样跨越多行。

上次我不得不做这样的事情时,我一次读一行,记下“/*”(或特定语言的分隔符)有多少级别,并且不打印任何内容,除非计数为 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: $!";

【讨论】:

    【解决方案2】:

    您想将$/ 设为本地,如

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

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

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

    【讨论】:

      【解决方案3】:

      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
      

      【讨论】:

        猜你喜欢
        • 2011-03-21
        • 2022-06-29
        • 1970-01-01
        • 2017-05-27
        • 1970-01-01
        • 2012-10-29
        • 1970-01-01
        • 2020-11-05
        • 2010-10-27
        相关资源
        最近更新 更多