다음과 같이 빈 Java 주석을 제거하고 싶습니다.
/**
*/
/*
*
*
*
*/
sed로 시도했지만 다음 명령은 빈 주석뿐만 아니라 모든 주석을 제거했습니다.
sed -r "/^\s*\/\*+\s*/,/\s*\*+\/\s*/d"
\s\*+\s
사이에 모양 선이 있는 범위 만 삭제하도록 sed에 어떻게 알릴 수 있나요 ? 내가 찾고 있어요http://www.grymoire.com/Unix/Sed.html#uh-29그러나 나는 거기서 해결책을 찾지 못했습니다.
추신: 다음 테스트 파일을 만들었습니다.
/**
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'
아이디어는 정규식이 전체 파일과 일치한다는 것입니다. 그러나 이 큰 교대에 대한 다른 대안에서는 다음과 같이 작동합니다.토크나이저.
기본적으로 파일을 통과하여 토큰으로 분할합니다. 텍스트는 우리가 찾고 있는 빈 주석, 큰따옴표로 묶인 문자열, 작은따옴표 문자( '\''
또는 같은 이스케이프 문자 포함 '\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가 이를 수행할 수 있지만 여러 줄 주석을 식별하는 것은 복잡합니다. 특히 리터럴 문자열이나 주석을 조심하고 올바르게 처리하려는 경우에는 더욱 그렇습니다 .*/
//
소스 파일은 일반적으로 메모리에 완전히 들어갈 만큼 작으므로 한 줄씩 처리해도 이점이 없습니다. 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 $&;}
}
'