我想删除空的 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 $&;}
}
'