한 줄의 "C" 스타일 주석을 "C++" 스타일로 변환하려고 합니다. 아래의 "sed"는 나쁘지 않지만, 선행 코드(주석 앞의 코드)에 "/"가 있으면 당연히 실패합니다.
sed -i 's,\(^[^\/]*\)\/\*\([^\*]*\)\*\/[ ]*$,\1\/\/\2,' filename
제가 할 수 있기를 바라는 것은 다음과 같습니다.
... [^\\/\\*] ...
즉, "/*"를 부정하는 것은 물론 작동하지 않지만 몇 시간 동안 검색한 후에도 찾을 수 없습니다.단순한이를 올바르게 수행하는 방법을 설명하십시오.( 이것은 로켓 과학이 아닌 것 같습니다.
예를 들어 다음 문자열은 다음과 같습니다.
blah blah /* comment */
blah blah / blah /* comment */
blah blah /* comment */ blah
blah blah / blah /* comment */ blah
...다음과 같이 변환되어야 합니다.
blah blah // comment
blah blah / blah // comment
blah blah /* comment */ blah (this CAN'T be converted)
blah blah / blah /* comment */ blah (this CAN'T be converted)
...분명히 "C" 주석 뒤에 코드가 있으면 변환이 발생하지 않습니다.
파일 전후를 주의 깊게 시각적으로 비교할 것이므로 텍스트에서 "/*"를 처리할 필요도 없고 여러 줄의 내용을 변환하고 싶지도 않습니다.
나는 이것이 "부정적인" 질문이라고 생각하지만 아마도 다른 방법이 있을 수도 있다는 점에 유의하십시오. "/*" 이전의 모든 항목을 캡처하면 됩니다. 방법은 상관없습니다.
아래 답변을 따라가세요
빌어 먹을! 나는 내가 기본적인 것을 완전히 오해했다는 것을 발견했습니다.
.*/\*
...읽기: "슬래시 별표 뒤에 슬래시 별표가 오는 것을 제외한 모든 것", 그래서 실제로 "neg"를 무료로 얻습니다 :-)
따라서 Barmar보다 한 단계 더 발전했습니다.
sed -i 's,^\(.*\)/\*\(.*\)\*/\s*$,\1//\2,' filename
...심지어 이것을 잡을 것입니다:
blah / * blah /* co / mme * nt */
그리고 출력:
blah / * blah // co / mme * nt
계발.
답변1
이 시도:
sed 's,^\(.*\)/\*\([^/]*\)\*/$,\1//\2,'
/
포함된 문자가 포함된 주석은 변환되지 않습니다 . 또는 다음을 사용할 수 있습니다.
sed 's,^\(.*\)/\*\(.*\)\*/$,\1//\2,'
같은 줄에 두 개의 주석이 있으면 잘못된 일이 됩니다.
blah blah /* comment1 */ blah /* comment2 */
로 변환됩니다
blah blah // comment1 */ blah /* comment2
부정적인 예측을 사용하여 내장된 주석을 테스트할 수 있으므로 PCRE 버전을 사용하는 것이 더 나을 수 있습니다 sed
.
또한 ,
명령에서 구분 기호로 사용한다는 것은 정규 표현식의 모든 문자를 s
이스케이프할 필요가 없다는 것을 의미합니다 /
. 이는 /
정규 표현식에 /
.
답변2
아마도 가장 안전한 접근 방식은 영향을 주지 않으려는 행을 먼저 테스트하고 b
일치하는 경우 스크립트를 종료하는 것입니다.
sed '\|\*/.*/\*|b'
*
모든 별표가 포함되어 있어 읽기가 약간 어렵지만 기본적으로 /*
if가 발생한 후에 */
sed
는 스크립트 실행을 종료하고 자동으로 줄을 인쇄한 다음 다음 줄을 당겨서 다음 줄 루프를 시작합니다. 일치하는 줄의 경우 그 뒤에 오는 명령은 실행되지 않습니다.
또 다른 방법은 est를 사용하는 것입니다 . 이는 t
성공적인 교체 후 목초지 태그가 제공되지 않으면 b
스크립트에서도 동일한 작업을 수행합니다 .b
s///
sed 's|/\*|&|2;t'
줄에서 두 번째로 나타나는 패턴을 자신의 패턴으로 바꾸려고 시도하며, 성공하면 같은 방식으로 분기됩니다 b
.
그래서...
sed 's|/\*|&|2;s|\*/|&|2;t
s|/\*\(.*\)\*/ *$|//\1|'
/*
... 후행 공백 문자 수에 관계없이 //
끝나는 줄의 첫 번째이자 유일한 발생을 대체합니다 . */
이는 이전에 발생한 모든 대체에 적용되기 때문에 작동하므로 t
둘 중 하나가 t
성공 하면 sed
분기됩니다.
하지만 저는 C나 C++에 익숙하지 않고 이 경우 무엇을 기대해야 할지 잘 모르기 때문에 여기서 실수를 저지르고 있을 수도 있습니다 . /\*.*\*/.*\*/
위의 스크립트는 2만 테스트해야 하거나 2만 b
테스트해야 할 수도 있습니다 . 그러나 적어도 나는 이 개념을 더 잘 아는 사람에게 전달할 수 있기를 바랍니다.*/
/*
답변3
우연히 위의 내용이 필요했지만 여러 줄도 필요했습니다. 그래서 Barmar의 답변을 내 자신의 일부 sed와 병합하여 이를 달성했습니다.
sed -e '/\/\*/,/\*\//{s/^\( *\)\/\*/\1~~/g;s/^\( *\) \*\//\1~~/g;s/^\( *\) \*/\1~~/g;s/~~/\/\//g};s/\*\*/\/\//g;s,^\(.*\)/\*\(.*\)\*/\s*$,\1//\2,'
(그런데 Mac에서는 gsed가 필요합니다. 그렇지 않으면 위의 오류가 발생합니다)
전/후 차이입니다
***************
*** 1,13 ****
! /*
FOO
! */
! /*
! * BAR
! */
! blah blah /* comment */
! blah blah / blah /* comment */
blah blah /* comment */ blah
blah blah / blah /* comment */ blah
--- 1,13 ----
! //
FOO
! //
! //
! // BAR
! //
! blah blah // comment
! blah blah / blah // comment
blah blah /* comment */ blah
blah blah / blah /* comment */ blah