如何使用 Perl 从文件中删除多行 C 注释?

Posted

技术标签:

【中文标题】如何使用 Perl 从文件中删除多行 C 注释?【英文标题】:How can I strip multiline C comments from a file using Perl? 【发布时间】:2010-10-27 00:31:45 【问题描述】:

谁能用正则表达式让我在一个文件中去除多行 cmets 和单行 cmets?

例如:

                  " WHOLE "/*...*/" HAS TO BE STRIPED OFF....."

1.   /* comment */
2.   /* comment1 */  code   /* comment2 */ #both /*comment1*/ and /*comment2*/ 
                                             #has to striped off and rest should 
                                                 #remain.
3.   /*.........
       .........
       .........
       ......... */

如果你有这个需要,我真的很感激你....在此先感谢。

【问题讨论】:

根据经验,我发现当您尝试以编程方式操作 C、XML、SQL 等语言时,您应该考虑使用解析器而不是正则表达式。我强烈建议学习解析器生成器、yacc、javacc 等。作为软件开发人员,这对我来说是巨大的回报。 @zimbu668 这是使用解析器非常过分的情况。这里没有嵌套,也没有复杂的结构,只有简单的 cmets 【参考方案1】:

这是一个常见问题解答:

perldoc -q comment

发现于perlfaq6:

如何使用正则表达式从文件中去除 C 风格的 cmets?

虽然这实际上是可以做到的,但它比您想象的要难得多。为了 例如,这个单行...

【讨论】:

您可以通过faq.perl.org(始终是最新版本)或 perldoc.perl.org 链接到 perlfaqs。这样,这些网站就可以为搜索答案的人提供良好的谷歌服务。 :)【参考方案2】:

还有一个非perl的答案:使用程序stripcmt:

StripCmt 是一个简单的实用程序 在 C 中从 C、C++ 中删除 cmets, 和 Java 源文件。在盛大 Unix 文本处理的传统 程序,它可以作为一个 FIFO(先进先出)过滤器或 接受命令行参数。

【讨论】:

另一个选项就是cpp【参考方案3】:

来自perlfaq6“如何使用正则表达式从文件中去除C风格的cmets?”:


虽然这实际上是可以做到的,但它比您想象的要难得多。比如这个单行

perl -0777 -pe 's/\*.*?\*/gs' foo.c

适用于许多但不是所有情况。你看,对于某些类型的 C 程序,特别是那些在引号字符串中看起来是 cmets 的程序来说,这太简单了。为此,您需要这样的东西,由 Jeffrey Friedl 创建,后来由 Fred Curtis 修改。

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

当然,这可以用 /x 修饰符写得更清晰,添加空格和 cmets。此处对其进行了扩展,由 Fred Curtis 提供。

s
   /\*         ##  Start of /* ... */ comment
   [^*]*\*+    ##  Non-* followed by 1-or-more *'s
   (
     [^/*][^*]*\*+
   )*          ##  0-or-more things which don't start with /
               ##    but do end with '*'
   /           ##  End of /* ... */ comment

 |         ##     OR  various things which aren't comments:

   (
     "           ##  Start of " ... " string
     (
       \\.           ##  Escaped char
     |               ##    OR
       [^"\\]        ##  Non "\
     )*
     "           ##  End of " ... " string

   |         ##     OR

     '           ##  Start of ' ... ' string
     (
       \\.           ##  Escaped char
     |               ##    OR
       [^'\\]        ##  Non '\
     )*
     '           ##  End of ' ... ' string

   |         ##     OR

     .           ##  Anything other char
     [^/"'\\]*   ##  Chars which doesn't start a comment, string or escape
   )
 defined $2 ? $2 : ""gxse;

稍作修改也删除了 C++ cmets,可能使用连续字符跨越多行:

 s#/\*[^*]*\*+([^/*][^*]*\*+)*/|//([^\\]|[^\n][\n]?)*?\n|("(\\.|[^"\\])*"|'(\\.|[^'\\])*'|.[^/"'\\]*)#defined $3 ? $3 : ""#gse;

【讨论】:

brian,这个功能几乎可以添加到 perl 中,似乎被问了这么多。至少是国际海事组织。 ...这就是为什么我们有 yacc、flex、bison、ANTLR 等工具的原因。这是你需要一个成熟的解析器而不是正则表达式的东西。 @Paul:这个功能已经在 Perl 中了。 Perl 是一种通用语言。我们不想为出现的每个任务添加内置功能。这就是模块的工作。【参考方案4】:

去掉/* */ cmets(包括多行)

s/\/\*.*?\*\///gs

我发布这个是因为它很简单,但是我相信它会在嵌入式 cmets 上绊倒

/* sdafsdfsdf /*sda asd*/ asdsdf */

但由于它们相当少见,我更喜欢简单的正则表达式。

【讨论】:

【参考方案5】:

包括测试:

use strict;
use warnings;
use Test::More qw(no_plan);
sub strip_comments 
  my $string=shift;
  $string =~ s#/\*.*?\*/##sg; #strip multiline C comments
  return $string;

is(strip_comments('a/* comment1 */  code   /* comment2 */b'),'a  code   b');
is(strip_comments('a/* comment1 /* comment2 */b'),'ab');
is(strip_comments("a/* comment1\n\ncomment */ code /* comment2 */b"),'a code b');

【讨论】:

会弄乱 /* 或 / 出现在字符串中。例如。字符串“This / string”不包含注释开头。 除了不处理字符串中的注释字符(甚至是多字符字符常量)之外,它也不处理反斜杠换行拼接,它允许开始斜杠后跟反斜杠、换行符,然后例如,星号。也不处理 C++ cmets(也可以有反斜杠换行符拼接)。它不处理三元组——唯一相关的是'??/',这意味着反斜杠。这有多重要取决于您的代码需要多么防弹。 mirod 的回答要好得多。 用空字符串替换 cmets 也是错误的。当令牌被意外拼接时,它会改变代码的语义。 C 标准要求在翻译阶段 3 中将 cmets 替换为单个空格字符。【参考方案6】:

在 Perl 中,您可以使用 CPAN:Regexp::Common::Comment 应该可以帮助您。我发现使用您描述的 cmets 的一种语言是 Nickle,但也许 php cmets 可以(// 也可以开始单行注释)。

请注意,在任何情况下,使用正则表达式去除注释都是危险的,语言的完整解析器风险要小得多。例如,正则表达式解析器可能会被 print "/*"; 之类的东西弄糊涂。

【讨论】:

以上是关于如何使用 Perl 从文件中删除多行 C 注释?的主要内容,如果未能解决你的问题,请参考以下文章

使用UltraEdit配置多行注释和取消多行注释

如何在 Perl 中输入多行注释? [复制]

从源文件中删除所有注释(单行/多行)和空行[重复]

如何用空格或缩进注释多行

visual studio 中如何对多行代码同时打上“//”或者同时删除注释符?求VS中的各种快

Perl 中多行注释的常见解决方法是啥?