使用 sed 删除 c 风格注释

使用 sed 删除 c 风格注释

我需要从我们的存储库中的所有文件中删除某种特征性的单行 C++ 注释。代码看起来像这样:

some_code
// characteristic_comment_to_delete
some_more_code // another_comment
another_line_with_code // characteristic_comment_to_delete
even_more_code

结果,我想得到这个:

some_code
some_more_code // another_comment
another_line_with_code
even_more_code

我使用 sed 命令使我的结果几乎和我想要的一样好:

$ sed -i -e 's&// characteristic_comment_to_delete.*&&g' some_file.cpp
some_code

some_more_code // another_comment
another_line_with_code
even_more_code

不幸的是,保留这些空行是不可接受的解决方案,因此我需要以某种方式改进我的命令,以便它删除整行,但前提是在删除此特定注释后将其保留为空白。

编辑:我显然没有以 root 身份运行这些命令。相应地更改了提示。另外,我不想删除所有评论,所以我不认为我的主题是重复其他线程。

答案1

Sed 有一个d用于删除整行的命令 - 它也可以采用任意(非/)分隔符,但是在第一次使用时需要对其进行转义\。所以你可以做类似的事情

$ sed -e '\#^// characteristic_comment_to_delete$#d' -e 's#// characteristic_comment_to_delete.*##' file
some_code
some_more_code // another_comment
another_line_with_code 
even_more_code

首先删除完全由 组成的行// characteristic_comment_to_delete,然后替换任何剩余的匹配项。

(我将您的更改&#以避免与 sed&替换运算符混淆)。

答案2

使用 GNU sed

sed 's|\s*// characteristic_comment_to_delete.*||;T;/./!d'

T是一个 GNU 扩展分支除非之前的s替换成功。因此,如果没有删除任何注释,我们就会分支,并/./!d跳过下一个(删除该行,除非它至少包含一个字符)。

标准等效:

sed '\/[[:space:]]*\/\/ characteristic_comment_to_delete.*/{s///;/./!d;}'

或者:

sed 's|[[:space:]]*// characteristic_comment_to_delete.*||
     t 1
     b
     :1
     /./!d'

仅当替换成功时,两者才会抑制空行。

答案3

如果您接受 AWK 解决方案:

awk -F "[   ]*//[   ]*characteristic_comment_to_delete.*" '$1 != "" { print $1; }' some_file.cpp

注意:该模式在方括号之间包含一个空格和一个制表符[ ]

此解决方案无法正确处理包含注释模式的字符串文字,例如
char text[] = "// characteristic_comment_to_delete bla bla";

答案4

我删除特定注释的琐碎任务变得比我预期的要复杂得多,但我找到了一个可行的解决方案,我将其分成几个单独的命令。主要问题是我有这样的行:

another_line_with_code // characteristic_comment_to_delete#xA;more_code // characteristic_comment_to_delete // characteristic_comment_to_delete

#xA;是换行符,但文件的写入方式对于 sed 来说被视为单行。

我必须使用 Perl,因为我无法回避这样一个事实:尽管理论上有很好的正则表达式,但 sed 太贪婪了。

使我能够删除仅包含注释的行的最终解决方案是(感谢 Steeldriver 将我指向“d”参数,我不知道这一点):

$ find . -type f -print0 | xargs -0 sed -i -e '\#^// characteristic_comment_to_delete\s*$#d'

并删除内嵌注释:

$ find . -type f -print0 | xargs -0 perl -pi -e 's|\s*// characteristic_comment_to_delete\s*
||g'

+

$ find . -type f -print0 | xargs -0 perl -pi -e 's|
// characteristic_comment_to_delete\s*||g'

+

$ find . -type f -print0 | xargs -0 perl -pi -e 's|\s*// characteristic_comment_to_delete\s*||g'

可以很容易地减少到只有两个命令,并且可能只用单个命令捕获所有情况,但上面已经完成了工作。谢谢大家!

相关内容