C ソースコードから文字列を削除する [終了]
-
18-09-2019 - |
質問
誰かが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 ではありません) が、末尾が \ で終わる複数行にまたがる文字列はサポートされる必要があります。
解決
あなたはソースコードをダウンロードすることができStripCmt (.tar.gz形式 - 5kBの)。それは自明小型だし、代わりにストライピング文字列に適応するにはあまりにも難しいことではありません(それはリリースします)GPL の下ます。
また、C文字列の公式の字句言語規則を調査する場合があります。私は見つけましたが、そうではないかもしれません決定的なこと。それは、などの文字列を定義します:
stringcon ::= "{ch}", where ch denotes any printable ASCII character (as specified by isprint()) other than " (double quotes) and the newline character.
他のヒント
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)
また、標準出力に出力します。