我有一个C文件,我从别的地方复制,但它有很多像下面的评论:
int matrix[20]; /* generate data */ for (index = 0 ;index < 20; index++) matrix[index] = index + 1; /* print original data */ for (index = 0; index < 5 ;index++)
如何删除/*
和*/
包含的所有注释。 有时,评论是由4-5行,我需要删除所有这些行。
基本上,我需要删除/*
和*/
之间的所有文本,甚至可以在\n
之间插入。 请帮助我使用sed
, awk
或perl
之一来执行此操作。
为什么不使用c预处理器来做到这一点? 你为什么只限于一个本土的正则表达式呢?
[编辑]这种方法也干净地处理Barts printf(".../*...")
场景
例:
[File: tc] /* This is a comment */ int main () { /* * This * is * a * multiline * comment */ int f = 42; /* * More comments */ return 0; }
。
$ cpp -P tc int main () { int f = 42; return 0; }
或者你可以删除空白并压缩一切
$ cpp -P tc | egrep -v "^[ \t]*$" int main () { int f = 42; return 0; }
没有必要重新发明轮子,是吗?
[编辑]如果你不想通过这种方式来扩展包含的文件和宏, cpp
提供了这个标志。 考虑:
[File:tc]
#include <stdio.h> int main () { int f = 42; printf(" /* "); printf(" */ "); return 0; }
。
$ cpp -P -fpreprocessed tc | grep -v "^[ \t]*$" #include <stdio.h> int main () { int f = 42; printf(" /* "); printf(" */ "); return 0; }
有一点需要注意,宏观扩张是可以避免的,但宏观的原始定义是从源头上剥离的。
参见perlfaq6 。 这是相当复杂的情况。
$/ = undef; $_ = <>; s#/\*[^*]*\*+([^/*][^*]*\*+)*/|("(\\.|[^"\\])*"|'(\\.|[^'\\])*'|.[^/"'\\]*)#defined $2 ? $2 : ""#gse; print;
一个警告 – 一旦你这样做了,你有一个测试场景来证明你刚刚删除了评论,没有什么价值? 如果你正在运行如此强大的正则表达式,我会确保某种测试(即使你之前/之后只记录行为)。
看看Inline :: Filters中的strip_comments
例程 :
sub strip_comments { my ($txt, $opn, $cls, @quotes) = @_; my $i = -1; while (++$i < length $txt) { my $closer; if (grep {my $r=substr($txt,$i,length($_)) eq $_; $closer=$_ if $r; $r} @quotes) { $i = skip_quoted($txt, $i, $closer); next; } if (substr($txt, $i, length($opn)) eq $opn) { my $e = index($txt, $cls, $i) + length($cls); substr($txt, $i, $e-$i) =~ s/[^\n]/ /g; $i--; next; } } return $txt; }
除非你明白这些后果,否则请不要使用cpp
:
$ cat tc #include <stdio.h> #define MSG "Hello World" int main(void) { /* ANNOY: print MSG using the puts function */ puts(MSG); return 0; }
现在,让我们通过cpp
运行它:
$ cpp -P tc -fpreprocessed #include <stdio.h> int main(void) { puts(MSG); return 0; }
显然,这个文件不再是要编译的。
考虑:
printf("... /* ..."); int matrix[20]; printf("... */ ...");
换句话说:我不会使用正则表达式来完成这个任务,除非你正在进行一次替换 ,并且肯定不会发生上述情况。
您必须使用C预处理程序与其他工具组合临时禁用特定的预处理程序功能(如扩展#defines或#include),所有其他方法在边缘情况下都将失败。 这将适用于所有情况:
[ $# -eq 2 ] && arg="$1" || arg="" eval file="\$$#" sed 's/a/aA/g;s/__/aB/g;s/#/aC/g' "$file" | gcc -P -E $arg - | sed 's/aC/#/g;s/aB/__/g;s/aA/a/g'
把它放在一个shell脚本中,并用你想要解析的文件的名字来调用它,或者用一个像“-ansi”这样的标志作为前缀来指定要应用的C标准。
在命令行上试试这个(用需要处理的文件列表替换“文件名”):
perl -i -wpe 'BEGIN{undef $/} s!/\*.*?\*/!!sg' file-names
该程序就地更改文件(用改正的输出覆盖原始文件)。 如果您只是想要输出而不更改原始文件,则省略“-i”开关。
说明:
perl -- call the perl interpreter -i switch to 'change-in-place' mode. -w print warnings to STDOUT (if there are any) p read the files and print $_ for each record; like while(<>){ ...; print $_;} e process the following argument as a program (once for each input record) BEGIN{undef $/} --- process whole files instead of individual lines. s! search and replace ... /\* the starting /* marker .*? followed by any text (not gredy search) \*/ followed by the */ marker !! replace by the empty string (ie remove comments) s treat newline characters \n like normal characters (remove multi-line comments) g repeat as necessary to process all comments. file-names list of files to be processed.
当我想要简短的CSS的东西,我使用这个:
awk -vRS='*/' '{gsub(/\/\*.*/,"")}1' FILE
这不会处理注释分隔符出现在字符串内的情况,但它比解决方案要简单得多。 显然,这不是防弹的,也不适合所有的事情,但是你比谁更了解你是否可以忍受。
我相信这个 是防弹的。
尝试使用下面的递归方式查找和删除Java脚本类型注释,XML类型注释和单行注释
/* This is a multi line js comments. Please remove me*/
for f in find pages/ -name "*.*"
; 做perl -i-wpe'BEGIN {undef $ /} s!/*.*?* / !! sg'$ f; DONE
<!-- This is a multi line xml comments. Please remove me -->
for f in find pages/ -name "*.*"
; 做perl -i-wpe'BEGIN {undef $ /} s!<! – 。*? – > !! sg'$ f; DONE
//This is single line comment Please remove me.
for f in find pages/ -name "*.*"
; 做sed -i的///.*//'$ f; DONE
注意:页面是一个根目录,上面的脚本也会在位于根目录和子目录的所有文件中查找和删除。
非常简单的使用gawk的例子。 在实施之前请测试很多次。 当然,它不会照顾其他评论风格//(在C ++中)
$ more file int matrix[20]; /* generate data */ for (index = 0 ;index < 20; index++) matrix[index] = index + 1; /* print original data */ for (index = 0; index < 5 ;index++) /* function(){ blah blah } */ float a; float b; $ awk -vRS='*/' '{ gsub(/\/\*.*/,"")}1' file int matrix[20]; for (index = 0 ;index < 20; index++) matrix[index] = index + 1; for (index = 0; index < 5 ;index++) float a; float b;