如何用sed删除空注释?

如何用sed删除空注释?

我想删除空的 Java 注释,如下所示:

/**
*/

/*
 *
 *
 *
*/

我用 sed 尝试过,但以下命令删除了所有注释,而不仅仅是空注释:

sed -r "/^\s*\/\*+\s*/,/\s*\*+\/\s*/d"

我怎样才能告诉 sed 只删除\s\*+\s其间有形状线的范围?我在看http://www.grymoire.com/Unix/Sed.html#uh-29但我在那里没有找到解决方案。

PS:我创建了以下测试文件:

/**
bla bla bla
*/

/*ba dff
 *dd fdf
 *d f
 *df df df
*/

/**
*/

/*
 *
 *
 *
*/

class Test
{
 some code...
}

第一种方法:

sed -n '/[^ \/\*]/p' /tmp/tmp

 bla bla bla
/*ba dff
 *dd fdf
 *d f
 *df df df
class Test
{
 some code...
}

其中一条评论的开头和结尾被删除。

perl -0777 -pe 's,\s*/\*[*\s]*\*/\s*, ,gs' < /tmp/tmp

/**
bla bla bla
*/

/*ba dff
 *dd fdf
 *d f
 *df df df
*/  class Test
{
 some code...
}

最后一条注释与类定义位于同一行。

warl0ck 的方法:

$ removeemptycomments /tmp/tmp








class Test
{
 some code...
}

答案1

sed 一次只处理一行。使用 perl 代替:

perl -0777 -pe 's,\s*/\*[*\s]*\*/\s*, ,gs'

这会将空注释及其周围的所有空格转换为单个空格(需要,否则int/* */i会变成inti其他空格)。现在,这意味着如果您有连续的空注释,您将有连续的空格,因此您可能需要将其更改为:

perl -0777 -pe 's,\s*(?:/\*[*\s]*\*/\s*)+, ,gs'

现在,为了保留间距,这取决于您想要做什么以及注释的布局方式。如果注释可能无处不在,并且您想在注释后保留缩进,但仍想压缩不必要的空间,您可以尝试:

perl -0777 -pe 's,(\s*)(?:\s*/\*[*\s]*\*/)+(\s*\n|\s*),"$1$2"=~/\n/?"\n":" ",ges'

也就是说,如果注释周围有换行符,则替换为换行符(以及注释后换行符后的原始缩进)或空格。

这对于 perl 是可能的,因为 perl 正则表达式交替运算符与其他正则表达式引擎相反,不要试图找到最长的匹配,而是依次查看交替的每个部分,直到有一个匹配为止。

现在,如果您想忽略字符串内可能出现的空注释(例如"/***/"),那么它会变得有点棘手,特别是当您必须考虑转义双引号或单引号内的双引号时。但是,perl 交替正则表达式运算符再次拯救了我们:

perl -0777 -pe 's,(\s*)(?:\s*/\*[*\s]*\*/)+(\s*\n|\s*)|(/\*.*?\*/|//.*?\n|"(?:\\.|.)*?"|'\''(?:\\.)?.*?'\''|.[^"/'\'']*),"$3"or"$1$2"=~/\n/?"\n":" ",ges'

这个想法是,正则表达式匹配整个文件,但是在这个大交替的不同替代方案中,其工作方式有点像分词器

基本上,它遍历文件并将其分割成标记。文本被视为一系列标记,这些标记要么是我们正在查找的空注释,要么是双引号字符串,要么是单引号字符(可能带有像'\''or 之类的转义符'\033'),要么是其他任何内容。

我们正在寻找的空注释标记被替换为空格或换行符,如上所述,其他任何内容都被替换为自身。所以它现在应该能够处理输入,例如

/* comments with " unmatched quotes ' */ /* */
  f('"', "/***/" /***/, "\"", "/****/")

正确。现在,由于不熟悉java语法,我想可能存在无法正常工作的极端情况,因此 java 专家将能够改进它(例如,在 C 中,您需要考虑三字母或反斜杠可以用来转义换行符,所以它会错过/*中间被破坏的a /\<LF>*,它在 java 中可能是相同的,所以你可以改进该代码以考虑到这一点)。

答案2

尝试打印预期而不是删除,在这种情况下更简单:

sed -n '/[^ \/\*]/p' file

这会尝试打印所有包含除 / 、空格或 * 之外的内容的行

答案3

sed '/\/\*/{:a;N;/\*\//!ba};/^\s*\/\*\+[*\s\n ]*\*\/\s*$/d'

在哪里

/\/\*/{:a;N;/\*\//!ba}

将所有注释字符串附加到一个字符串中

/^\s*\/\*\+[*\s\n ]*\*\/\s*$/d

会检查是否为空评论,如果是则删除。

答案4

虽然 sed 可以做到这一点,但识别多行注释很复杂,特别是如果您想小心并正确处理文字字符串或注释中的/*or 。*///

源文件通常足够小,足以完全装入内存,因此逐行处理它们没有任何好处。使用 Perl 和 Python 等语言将整个文件加载到内存中,然后进行部分标记化。这是一个未经测试的 Perl 程序。

perl -0777 -ne '
    while ($_ ne "") {
        if (s~\A[^/"]+|\A\x27\\?.\x27|\A"(?:[^\\"]|\\.")~~) { print $&; } # not a comment
        elsif (s~\A//(.*)$~~m) { $c = $&; print $c if $1 =~ /\S/ } # // comment
        elsif (s~\A/\*(.*?)(\*/|\z)~~) { # /*comment*/
            $c = $&;
            if ($1 =~ /\A[^\n\t *]/ || !$2) {
                print $c; # non-empty or non-terminated comment
            } else {
                $c =~ s/[^\n]//g; # empty comment: retain the newlines
                print $c;
            }
        } else {s~\A.~~; print $&;}
    }

'

相关内容