当//注释出现在/ * * /中时,sed用/ * * / comments替换//除外

时间:2012-08-17 04:55:55

标签: c sed comments

我面临的问题是ANSI编译器需要C风格注释。

所以我试图将我现有的注释转换为符合C标准ISO C89。

我正在寻找一个SED表达式来替换//注释/ *注释除了//注释出现在/ * * / comments中(这会破坏注释)。

我试过这个(范围表达式)无济于事:

sed -e '/\/*/,/*\//! s_//\(.*\)_/*\1 */_' > filename

有什么方法可以忽略像这样的评论中的1行评论,但改变其他一切吗?

/**********************************
* Some comment
* an example bit of code within the comment followed by a //comment
* some more comment
***********************************/
y = x+7; //this comment must be changed

谢谢!

6 个答案:

答案 0 :(得分:4)

这是一个用C编写的经过轻度测试的过滤器,可以执行您想要的转换。关于这个过滤器做什么的一些评论即使不是不可能用正则表达式处理也很困难:

  • 它忽略了用引号括起来的注释式序列(因为它们不是注释)
  • 如果正在转换的C99注释包含可以开始或结束C89注释的内容,则会触发该序列,因此注释中不会嵌套注释或过早结束(嵌套/*或{{ 1}}变为*//+)。我不确定你是否需要这个(如果你不需要,它应该很容易删除)
  • 上述嵌套注释的修改仅发生在正在转换的C99注释中 - 已经C89样式的注释内容不会更改。
  • 它不处理三字符或有向图(我认为这只允许错过一个以三字组/|启动的转义序列或行结束延续的可能性。)

当然,您需要执行自己的测试,以确定它是否适合您的目的。

??/

一些放纵的评论:很多年前,我工作过的一家商店想要强加一个禁止C99风格评论的编码标准,理由是即使我们当时使用的编译器对它们没有任何问题,代码也可能必须移植到不支持它们的编译器。我(和其他人)成功地认为这种可能性是如此遥远,以至于基本上是不存在的,并且即使它确实发生了,也可以很容易地编写使评论兼容的转换例程。我们被允许使用C99 / C ++风格的评论。

我现在认为我的誓言已经实现了,而且可能已经解除了我的任何诅咒。

答案 1 :(得分:0)

如果你不能使用@ephemient的建议,那么你需要跨多行应用你的正则表达式,这不是sed的默认行为。 sed有一个保持缓冲区,它允许你将多个字符串附加在一起并将正则表达式应用于连接字符串。

sed表达式如下所示:

sed '1h;1!H;${;g;s/your-matcher-regex/replacement-regex/g;}'

1h - 如果是第一行,则将该行放入保留缓冲区(先将其清空)

1!H - 如果不是第一行,则附加到保持缓冲区

$ {...} - 如果是最后一行,执行此sed命令

现在,即使/ *和* /位于不同的行上,您的匹配表达式仍然有效。

答案 2 :(得分:0)

awk '{if($0~/\/\//){sub(/\/\//,"\/\*");$0=$0"*/"};print}' temp

答案 3 :(得分:0)

使用任何可以为/*//注释输出不同标记的转换器将代码转换为彩色HTML,使用perl / awk / sed / whatever处理输出,然后剥离标记。

答案 4 :(得分:0)

你可以(几乎)完全用sed执行此操作,只需要拨打一次tr

translate_comments_prepare.sed

s/\\/\\\\/g  # escape current escape characters
s/\$/\\S/g   # write all occurrences of $ as \S
s/(/\\o/g    # replace open braces with \o
s/)/\\c/g    # replace closing braces with \c
s/$/$/       # add a $ sign to the end of each line
s_/\*_(_g    # replace the start of comments with (
s_\*/_)_g    # replace the end of comments with )

然后我们通过tr -d '\n'管道“预处理”步骤的结果来加入所有行(我还没有想出一个从sed内做到这一点的好方法)。

然后我们做了真正的工作:

translate_comments.sed

s_//\([^$]*\)\$_(\1)$_g  # replace all C++ style comments (even nested ones)
:b                       # while loop
                         # remove nested comment blocks:
                         #   (foo(bar)baz) --> (foobarbaz)
s/(\([^()]*\)(\([^()]*\))\([^()]*\))/(\1\2\3)/
tb                       # EOF loop
s_(_/*_g                 # reverse the steps done by the preparation phase
s_)_*/_g                 # ...
s/\$/\n/g                # split lines that were previously joined
s/\\S/$/g                # replace escaped special characters
s/\\o/(/g                # ...
s/\\c/)/g                # ...
s/\\\(.\)/\1/g           # ...

然后我们基本上把所有东西放在一起

sed -f translate_comments_prepare.sed | tr -d '\n' | sed translate_comments.sed

答案 5 :(得分:0)

这可能适合你(GNU sed):

sed ':a;$!{N;ba};s/^/\x00/;tb;:b;s/\x00$//;t;s/\x00\(\/\*[^*]*\*\+\([^/*][^*]*\*\+\)*\/\)/\1\x00/;tb;s/\x00\/\/\([^\n]*\)/\/*\1\*\/\x00/;tb;s/\x00\(.\)/\1\x00/;tb' file

说明:

  • :a;$!{N;ba}将文件篡改到模式空间
  • s/^/\x00/设置标记N.B.这可以是文件中找不到的任何字符
  • tb;:b跳转到占位符b
  • 重置替换开关
  • s/\x00$//;t标记已到达文件末尾。全部完成。
  • s/\x00\(\/\*[^*]*\*\+\([^/*][^*]*\*\+\)*\/\)/\1\x00/;tb此正则表达式匹配c样式注释,如果为真,则标记会传递它们。
  • s/\x00\/\/\([^\n]*\)/\/*\1\*\/\x00/;tb此正则表达式匹配单行注释,替换为c样式注释,如果为真,则标记传递它们。
  • s/\x00\(.\)/\1\x00/;tb此正则表达式匹配任何单个字符,如果为真,则会将标记传递给它。