从C源代码中删除字符串

时间:2009-08-18 14:55:28

标签: c string code-formatting utility reformatting

有人能指出我从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;
}

我正在寻找的是一个与stripcmt非常相似的程序 只是我想剥离字符串而不是评论。

我正在寻找已经开发的程序,而不仅仅是一些方便的正则表达式 因为当你开始考虑所有角落情况(字符串中的引号,多行字符串等) 事情通常比最初出现的事情(更复杂)更复杂。和 RE有什么限制可以实现,我怀疑这项任务是不可能的。 如果你认为你有一个极其强大的正则表达式,可以随意提交,但请不要像天真的sed 's/"[^"]*"//g'那样建议。

(不需要在评论中对(可能是未结束的)字符串进行特殊处理,这些字符串将首先删除)

支持带有嵌入换行符的多行字符串并不重要(不合法C),但必须支持跨越以\结尾的多行的字符串。

这与some other questions几乎相同,但我没有找到任何工具的参考。

4 个答案:

答案 0 :(得分:5)

C(和大多数其他编程语言)中的所有令牌都是“常规”。也就是说,它们可以通过正则表达式进行匹配。

C字符串的正则表达式:

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

正则表达式并不难理解。基本上字符串文字是一对双引号围绕着一堆:

  • 非特殊(非引用/反斜杠/换行符)字符
  • escapes,以反斜杠开头,然后包含以下之一:
    • 一个简单的逃脱角色
    • 1到3个八进制数字
    • x和1个或更多十六进制数字

这是基于C89 / C90规范的第6.1.4和6.1.3.4节。如果在C99中有其他任何东西悄悄进入,这将无法理解,但这应该不难解决。

这是一个python脚本,用于过滤删除字符串文字的C源文件:

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字面正则表达式与字符串字面值非常相似。

答案 1 :(得分:4)

您可以下载source code to StripCmt(.tar.gz - 5kB)。它很小,并且不应该太难以适应条纹字符串(它是released under the GPL)。

您可能还想调查C字符串的官方词汇语言规则。我很快就找到了this,但它可能不是确定的。它将字符串定义为:

stringcon ::= "{ch}", where ch denotes any printable ASCII character (as specified by isprint()) other than " (double quotes) and the newline character.

答案 2 :(得分:0)

在红宝石中:

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

打印到标准输出

答案 3 :(得分:0)

在Python中使用pyparsing:

from pyparsing import dblQuotedString

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

同时打印到stdout。