質問

誰かがCソースコードから文字列を取り除くプログラムを教えてくれませんか?例

#include <stdio.h>
static const char *place = "world";
char * multiline_str = "one \
two \
three\n";
int main(int argc, char *argv[])
{
        printf("Hello %s\n", place);
        printf("The previous line says \"Hello %s\"\n", place);
        return 0;
}

になる

#include <stdio.h>
static const char *place = ;
char * multiline_str = ;
int main(int argc, char *argv[])
{
        printf(, place);
        printf(, place);
        return 0;
}

私が探しているのは非常によく似たプログラムです ストリップCMTコメントではなく文字列を削除したいだけです。

便利な正規表現だけでなく、すでに開発されたプログラムを探している理由は、すべてのコーナーケース(文字列内の引用、マルチライン文字列など)を検討し始めると、通常は(はるかに)より複雑になり始めます。最初に表示されます。そして REが達成できることには限界がある。持っていると思う場合は、 非常に 堅牢な正規表現を自由に送信できますが、素朴なものは投稿しないでください。 sed 's/"[^"]*"//g' 提案のようなもの。

(コメント内の (おそらく終了していない) 文字列を特別に処理する必要はありません。それらの文字列は最初に削除されます)

改行が埋め込まれた複数行の文字列のサポートは重要ではありません (合法的な C ではありません) が、末尾が \ で終わる複数行にまたがる文字列はサポートされる必要があります。

これは、とほぼ同じです。 いくつかの 他の 質問, しかし、ツールへの言及は見つかりませんでした。

他のヒント

C (および他のほとんどのプログラミング言語) のトークンはすべて「正規」です。つまり、正規表現で照合できます。

C 文字列の正規表現:

"([^"\\\n]|\\(['"?\\abfnrtv]|[0-7]{1,3}|x[0-9a-fA-F]+))*"

正規表現を理解するのはそれほど難しくありません。基本的に、文字列リテラルは、以下のものを二重引用符で囲んだものです。

  • 特殊でない (非引用符/バックスラッシュ/改行) 文字
  • バックスラッシュで始まり、次のいずれかで構成されるエスケープ。
    • 単純なエスケープ文字
    • 1 ~ 3 の 8 進数
    • x および 1 つ以上の 16 進数

これは、C89/C90 仕様のセクション 6.1.4 および 6.1.3.4 に基づいています。C99 に他の何かが忍び込んだ場合、これはそれを捕らえませんが、修正するのは難しくないはずです。

C ソース ファイルをフィルタリングして文字列リテラルを削除する Python スクリプトを次に示します。

import re, sys
regex = re.compile(r'''"([^"\\\n]|\\(['"?\\abfnrtv]|[0-7]{1,3}|x[0-9a-fA-F]+))*"''')
for line in sys.stdin:
  print regex.sub('', line.rstrip('\n'))

編集:

上記を投稿した後、すべての C トークンが正規であるのは事実ですが、すべてをトークン化しないと問題が発生する可能性があることに気づきました。特に、別のトークンであるべきものに二重引用符が表示されると、庭の道に誘導される可能性があります。コメントはすでに削除されているとおっしゃいました。そのため、他に本当に考慮する必要があるのは文字リテラルだけです (ただし、私が使用しようとしているアプローチは、コメントを処理するために簡単に拡張できます)。以下は、文字リテラルを処理するより堅牢なスクリプトです。

import re, sys
str_re = r'''"([^"\\\n]|\\(['"?\\abfnrtv]|[0-7]{1,3}|x[0-9a-fA-F]+))*"'''
chr_re = r"""'([^'\\\n]|\\(['"?\\abfnrtv]|[0-7]{1,3}|x[0-9a-fA-F]+))'"""

regex = re.compile('|'.join([str_re, chr_re]))

def repl(m):
  m = m.group(0)
  if m.startswith("'"):
    return m
  else:
    return ''
for line in sys.stdin:
  print regex.sub(repl, line.rstrip('\n'))

基本的に、文字列と文字リテラルのトークンを検索し、文字リテラルはそのままにして、文字列リテラルを削除します。char リテラル正規表現は、文字列リテラル正規表現と非常によく似ています。

Rubyでます:

#!/usr/bin/ruby
f=open(ARGV[0],"r")
s=f.read
puts(s.gsub(/"(\\(.|\n)|[^\\"\n])*"/,""))
f.close

標準出力にプリント

Pythonでpyparsingを使用します:

from pyparsing import dblQuotedString

source = open(filename).read()
dblQuotedString.setParseAction(lambda : "")
print dblQuotedString.transformString(source)

また、標準出力に出力します。

scroll top