Python を使用して C および C++ のコメントを削除しますか?

これは、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 はフラグを取らないので、最初にパターンをコンパイルする必要がありました.

編集 2: 文字リテラルが追加されました。文字リテラルには、文字列の区切り記号として認識される引用符が含まれている可能性があるためです。

編集 3: 正当な表現 int/**/x=5; のケースを修正しました intx=5; になります コメントを空の文字列ではなくスペースに置き換えることにより、コンパイルされません。


C (および C++) のコメントはネストできません。正規表現はうまく機能します:

//.*?\n|/\*.*?\*/

これには「Single line」フラグ (Re.S) が必要です。 ) C コメントは複数行にまたがる可能性があるためです。

def stripcomments(text):
    return re.sub('//.*?\n|/\*.*?\*/', '', text, flags=re.S)

このコードは機能するはずです。

/編集:上記のコードは実際に行末について仮定していることに注意してください!このコードは、Mac テキスト ファイルでは機能しません。ただし、これは比較的簡単に修正できます。

//.*?(\r\n?|\n)|/\*.*?\*/

この正規表現は、行末に関係なく、すべてのテキスト ファイルで機能するはずです (Windows、Unix、および Mac の行末をカバーします)。

/編集:MizardX と Brian (コメント内) は、文字列の処理について有効な発言をしました。上記の正規表現は、文字列の追加処理を持つ解析モジュールから抽出されているため、私はそれを完全に忘れていました。 MizardX のソリューションは非常にうまく機能するはずですが、二重引用符で囲まれた文字列しか処理できません。


C では、コメントが処理される前にバックスラッシュと改行が削除され、トリグラフがその前に処理されることを忘れないでください (??/ はバックスラッシュのトリグラフであるため)。私は SCC (strip 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 */

これはトライグラフを示していません。行末に複数のバックスラッシュを使用できることに注意してください。ただし、行のスプライシングでは、バックスラッシュの数は気にされませんが、その後の処理では問題になる可能性があります。これらすべてのケースを処理する単一の正規表現を作成することは簡単ではありません (しかし、それは不可能ではありません)。