Python을 사용하여 C 및 C++ 코멘트를 삭제하시겠습니까?
문자열에서 C와 C++ 코멘트를 삭제하는 Python 코드를 찾고 있습니다.(문자열에 C 소스 파일 전체가 포함되어 있다고 가정합니다.)
하여 .을 할 수 있습니다만, 해서 Regex의 네스팅이 것은 ./*
, 또는, 「」가 //
a /* */
.
이상적으로는, 곤란한 경우에 적절히 대처하는, 순진하지 않은 실장이 바람직합니다.
이것은 C++ 스타일의 코멘트, C 스타일의 코멘트, 문자열 및 단순 네스트 처리를 합니다.
def comment_remover(text):
def replacer(match):
s = match.group(0)
if s.startswith('/'):
return " " # note: a space and not an empty string
else:
return s
pattern = re.compile(
r'//.*?$|/\*.*?\*/|\'(?:\\.|[^\\\'])*\'|"(?:\\.|[^\\"])*"',
re.DOTALL | re.MULTILINE
)
return re.sub(pattern, replacer, text)
문자열 내의 주석 마커는 주석을 시작하지 않으므로 문자열을 포함해야 합니다.
편집: re.sub은 플래그를 받지 않았기 때문에 먼저 패턴을 컴파일해야 했습니다.
Edit2: 문자열 구분자로 인식될 수 있는 따옴표를 포함할 수 있으므로 문자 리터럴이 추가되었습니다.
Edit3: 법적 표현이 있는 경우를 수정했습니다.int/**/x=5;
될 것이다intx=5;
빈 문자열이 아닌 공백으로 코멘트를 치환하면 컴파일되지 않습니다.
C(및 C++) 코멘트는 네스트 할 수 없습니다.정규 표현은 올바르게 기능합니다.
//.*?\n|/\*.*?\*/
를 위해서는 " 플래그("한줄가 필요합니다.Re.S
C 코멘트는 여러 행에 걸쳐 있을 수 있기 때문입니다.
def stripcomments(text):
return re.sub('//.*?\n|/\*.*?\*/', '', text, flags=re.S)
이 코드는 동작합니다.
/EDIT: 상기의 코드는, 실제로 행의 엔딩에 대해 상정하고 있습니다.이 코드는 Mac 텍스트 파일에서는 작동하지 않습니다.그러나 이는 비교적 쉽게 수정할 수 있습니다.
//.*?(\r\n?|\n)|/\*.*?\*/
이 정규 표현은 행의 끝(Windows, Unix 및 Mac 행의 끝)에 관계없이 모든 텍스트파일로 동작합니다.
/EDIT: MizardX와 Brian(댓글)이 문자열 처리에 대해 유효한 발언을 했습니다.위의 regex는 문자열에 대한 추가 처리가 있는 해석 모듈에서 추출되었기 때문에 완전히 잊고 있었습니다.MizardX의 솔루션은 매우 잘 작동하지만 이중 따옴표로 묶인 문자열만 처리합니다.
C에서는 코멘트가 처리되기 전에 백슬래시 뉴라인이 삭제되고 그 전에 삼각형이 처리된다는 점에 유의하십시오(?/는 백슬래시의 삼각형이므로).나는 SCC(스트립 C/C++ 코멘트)라는 C 프로그램을 가지고 있는데, 이것은 테스트 코드의 일부입니다.
" */ /* SCC has been trained to know about strings /* */ */"!
"\"Double quotes embedded in strings, \\\" too\'!"
"And \
newlines in them"
"And escaped double quotes at the end of a string\""
aa '\\
n' OK
aa "\""
aa "\
\n"
This is followed by C++/C99 comment number 1.
// C++/C99 comment with \
continuation character \
on three source lines (this should not be seen with the -C fla
The C++/C99 comment number 1 has finished.
This is followed by C++/C99 comment number 2.
/\
/\
C++/C99 comment (this should not be seen with the -C flag)
The C++/C99 comment number 2 has finished.
This is followed by regular C comment number 1.
/\
*\
Regular
comment
*\
/
The regular C comment number 1 has finished.
/\
\/ This is not a C++/C99 comment!
This is followed by C++/C99 comment number 3.
/\
\
\
/ But this is a C++/C99 comment!
The C++/C99 comment number 3 has finished.
/\
\* This is not a C or C++ comment!
This is followed by regular C comment number 2.
/\
*/ This is a regular C comment *\
but this is just a routine continuation *\
and that was not the end either - but this is *\
\
/
The regular C comment number 2 has finished.
This is followed by regular C comment number 3.
/\
\
\
\
* C comment */
이것은 삼각자를 설명하지 않는다.줄의 끝에 여러 개의 백슬래시가 있을 수 있지만 줄 스플라이싱은 개수에 관계없이 후속 처리에서 발생할 수 있습니다.기타. 이러한 모든 경우를 처리하기 위해 하나의 regex를 작성하는 것은 간단하지 않습니다(그러나 그것은 불가능과는 다릅니다).
pygragments를 사용하여 문자열을 해석하고 해당 문자열에서 코멘트가 되는 모든 토큰을 무시합니다.Javascript, SQL, C Like 등 pygrments 목록에 있는 모든 렉서에게 매력적으로 작동합니다.
from pygments import lex
from pygments.token import Token as ParseToken
def strip_comments(replace_query, lexer):
generator = lex(replace_query, lexer)
line = []
lines = []
for token in generator:
token_type = token[0]
token_text = token[1]
if token_type in ParseToken.Comment:
continue
line.append(token_text)
if token_text == '\n':
lines.append(''.join(line))
line = []
if line:
line.append('\n')
lines.append(''.join(line))
strip_query = "\n".join(lines)
return strip_query
C와 같은 언어를 사용하는 경우:
from pygments.lexers.c_like import CLexer
strip_comments("class Bla /*; complicated // stuff */ example; // out",CLexer())
# 'class Bla example; \n'
SQL 언어 사용:
from pygments.lexers.sql import SqlLexer
strip_comments("select * /* this is cool */ from table -- more comments",SqlLexer())
# 'select * from table \n'
Javascript Like Languages 작업:
from pygments.lexers.javascript import JavascriptLexer
strip_comments("function cool /* not cool*/(x){ return x++ } /** something **/ // end",JavascriptLexer())
# 'function cool (x){ return x++ } \n'
이 코드는 코멘트만 삭제하기 때문에 이상한 값은 남습니다.이 솔루션은 무효 입력에도 대응할 수 있는 매우 견고한 솔루션입니다.
이 게시물은 Markus Jarderot의 게시물에 대한 코멘트에서 설명한 Markus Jarderot의 코드 개선에 대한 코드화된 버전을 제공합니다(원래 코드를 제공해 주셔서 감사합니다).
개선 사항을 좀 더 자세히 설명하려면:이것에 의해, 회선 번호가 그대로 유지됩니다.(이것은, C/C++ 코멘트를 치환하는 문자열내의 줄바꿈 문자를 그대로 유지하는 것에 의해서 행해집니다).
이 버전의 C/C++ 댓글 삭제 기능은 회선 번호(원문 텍스트에 유효한 회선 번호)를 포함한 에러 메시지(파싱 오류 등)를 사용자에게 생성하는 경우에 적합합니다.
import re
def removeCCppComment( text ) :
def blotOutNonNewlines( strIn ) : # Return a string containing only the newline chars contained in strIn
return "" + ("\n" * strIn.count('\n'))
def replacer( match ) :
s = match.group(0)
if s.startswith('/'): # Matched string is //...EOL or /*...*/ ==> Blot out all non-newline chars
return blotOutNonNewlines(s)
else: # Matched string is '...' or "..." ==> Keep unchanged
return s
pattern = re.compile(
r'//.*?$|/\*.*?\*/|\'(?:\\.|[^\\\'])*\'|"(?:\\.|[^\\"])*"',
re.DOTALL | re.MULTILINE
)
return re.sub(pattern, replacer, text)
Python 솔루션이 아니라 C/C++ 프리프로세서와 같이 코멘트를 삭제하는 방법을 이해할 수 있는 툴을 사용할 수도 있습니다.GNU CPP의 방법은 다음과 같습니다.
cpp -fpreprocessed foo.c
다음과 같은 것이 도움이 되었습니다.
from subprocess import check_output
class Util:
def strip_comments(self,source_code):
process = check_output(['cpp', '-fpreprocessed', source_code],shell=False)
return process
if __name__ == "__main__":
util = Util()
print util.strip_comments("somefile.ext")
이것은 서브프로세스와 cpp 프리프로세서의 조합입니다.프로젝트에는 "Util"이라는 유틸리티 클래스가 있으며, 사용/필요한 다양한 도구를 보관하고 있습니다.
최근에 교수님이 코드 리뷰를 위해 제출하기 전에 소스 코드에서 자바독을 삭제하도록 요구하는 수업을 들었을 때 우연히 이 문제를 발견했습니다.여러 번 이 작업을 수행해야 했지만 javadoc html 파일도 생성해야 했기 때문에 javadoc을 영구적으로 제거할 수 없었습니다.여기 제가 만든 작은 비단뱀 대본이 있습니다.javadoc은 /**로 시작하여 */로 끝나므로 스크립트는 이러한 토큰을 검색하지만 필요에 따라 스크립트를 수정할 수 있습니다.또한 한 줄의 블록댓글과 블록댓글이 끝나지만 블록댓글이 끝나는 행과 같은 줄에 아직 코멘트되지 않은 코드가 있는 경우도 처리합니다.도움이 됐으면 좋겠네요!
경고: 이 스크립트는 전달된 파일의 내용을 수정하여 원래 파일에 저장합니다.다른 곳에 백업을 두는 것이 현명할 것입니다.
#!/usr/bin/python
"""
A simple script to remove block comments of the form /** */ from files
Use example: ./strip_comments.py *.java
Author: holdtotherod
Created: 3/6/11
"""
import sys
import fileinput
for file in sys.argv[1:]:
inBlockComment = False
for line in fileinput.input(file, inplace = 1):
if "/**" in line:
inBlockComment = True
if inBlockComment and "*/" in line:
inBlockComment = False
# If the */ isn't last, remove through the */
if line.find("*/") != len(line) - 3:
line = line[line.find("*/")+2:]
else:
continue
if inBlockComment:
continue
sys.stdout.write(line)
아시는지 모르겠지만sed
UNIX 기반(Windows 사용 가능) 텍스트 구문 분석 프로그램입니다만, 파일에서 C/C++ 코멘트를 삭제하는 sed 스크립트를 찾았습니다.예를 들어 문자열 선언 등에 '//' 및 '/*'이 있으면 무시됩니다.Python 내부에서는 다음 코드를 사용하여 사용할 수 있습니다.
import subprocess
from cStringIO import StringIO
input = StringIO(source_code) # source_code is a string with the source code.
output = StringIO()
process = subprocess.Popen(['sed', '/path/to/remccoms3.sed'],
input=input, output=output)
return_code = process.wait()
stripped_code = output.getvalue()
프로그램에서는 ★★★★★★★★★★★★★★★★★★★★★★★★★.source_code
++ 소스 이며, 으로는 C/C++ 로서 C/C/C++ 로 합니다.stripped_code
는, 코멘트를 삭제한 상태로 C/C++ 코드를 보관 유지합니다.는, 이 파일을 할 수 .input
★★★★★★★★★★★★★★★★★」output
(변수)입니다.input
「」, 「」,output
★★★★★★★★★★★★★★★★★★」remccoms3.sed
는 상기 링크의 파일로, 디스크상의 판독 가능한 장소에 보존할 필요가 있습니다. sed
할 수 있으며 GNU/ 및 X 에 기본적으로 에 windows 、 GNU / Linux Distros 、 Mac OS X 。
이것은 순수 Python 솔루션보다 더 나을 것입니다. 수고를 들일 필요가 없습니다.
문자열 리터럴에 주석 구문에 일치하는 후속 문자가 포함되어 있는 경우 등 정규 표현 대소문자가 손실될 수 있습니다.이 문제를 해결하려면 파싱 트리가 정말 필요해요.
py++ 를 이용해, GCC 를 사용해 C++ 소스를 해석할 수 있습니다.
Py++는 휠을 재창조하지 않습니다.GCC C++ 컴파일러를 사용하여 C++ 소스 파일을 해석합니다.좀 더 정확히 말하면, 툴 체인은 다음과 같습니다.
소스 코드가 GCC-XML GCC-XML에 전달되어 GCC C++ 컴파일러 GCC-XML이 GCC의 내부 표현에서 C++ 프로그램의 XML 설명을 생성합니다.Py++는 피그ccml 패키지를 사용하여 GCC-XML 생성 파일을 읽습니다.결론은, 모든 선언이 올바르게 읽혀지고 있는 것을 확인할 수 있습니다.
아니면 아닐 수도 있죠 어쨌든 이건 단순한 파싱이 아니에요
@ RE 기반 솔루션 - 입력을 제한하지 않는 한(예를 들어 매크로 없음) 가능한 모든 '어색한' 사례를 올바르게 처리하는 RE를 찾을 수 없습니다.방탄해결을 위해서는 진짜 문법을 활용하는 것 외에는 선택의 여지가 없습니다.
또한 피톤이 아닌 답변도 있습니다. 프로그램 스트립cmt를 사용하십시오.
StripCmt는 C, C++ 및 Java 소스 파일에서 주석을 제거하기 위해 C로 작성된 단순한 유틸리티입니다.Unix 텍스트 처리 프로그램의 일반적인 전통에서, 이것은 FIFO(First In - First Out) 필터로 기능하거나 명령줄에서 인수를 받아들일 수 있습니다.
이것을 완벽하게 하기 위해서 실제로 해석 트리가 필요한 것은 아니지만, 실제로는 컴파일러의 프런트 엔드에서 생성되는 것과 동등한 토큰 스트림이 필요합니다.이러한 토큰 스트림은 반드시 행 연속 댓글 시작, 문자열 내 댓글 시작, 삼각파 정규화 등 모든 이상함을 처리해야 합니다.토큰 스트림이 있는 경우 주석을 쉽게 삭제할 수 있습니다.(실제 해석 트리를 생성하는 실제 파서의 프런트 엔드와 같은 토큰 스트림을 생성하는 툴이 있습니다).
토큰이 정규 표현에 의해 개별적으로 인식된다는 것은 원칙적으로 코멘트 어휘소를 선택하는 정규 표현을 쓸 수 있음을 나타냅니다.토큰라이저(적어도 우리가 작성한 것)에 대해 설정된 정규 표현식이 실제로 복잡하다는 것은 실제로 이 작업을 수행할 수 없다는 것을 의미합니다. 개별적으로 작성하는 것은 충분히 어려웠기 때문입니다.완벽하게 하고 싶지 않다면 위의 RE 솔루션 대부분은 문제 없습니다.
코드 난독화기를 만들지 않는 한 왜 스트립 코멘트를 원하는지 알 수 없습니다.이 경우, 당신은 그것을 완벽하게 이해해야 합니다.
언급URL : https://stackoverflow.com/questions/241327/remove-c-and-c-comments-using-python
'programing' 카테고리의 다른 글
vue v-if 문을 사용하여 변수가 비어 있는지 또는 null인지 확인합니다. (0) | 2022.07.16 |
---|---|
닫힘 소켓과 종료 소켓의 차이 (0) | 2022.07.16 |
Vuex - 변환 중인 업데이트 개체 (0) | 2022.07.11 |
VueJS 컴포넌트를 Google Map Infowindow로 렌더링 (0) | 2022.07.11 |
메서드 내 로컬 변수 상태에 액세스하는 방법 - Vue? (0) | 2022.07.11 |