2009-08-18 25 views
2

任何人都可以指向一个从C源代码中去除字符串的程序吗?例如从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),但必须支持跨越以\结尾的多行的字符串。

这几乎与someotherquestions一样,但我没有发现任何工具的参考。

+3

纯粹是为了利益,为什么你需要这样的工具?换句话说,你将如何处理该工具的输出? – 2009-08-18 15:14:02

+0

它用于令牌搜索。例如“在哪些文件中函数x,y和z叫”。通过预处理,删除评论和字符串我会得到一个准确的结果。目前这些琴弦正在产生噪音。 – hlovdal 2009-08-18 15:41:10

+2

使用理解C的代码分析工具不是更好吗?有很多。 – 2009-08-18 16:17:57

回答

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. 
+0

我没有想过检查stripcmt的来源。修改很简单。 – hlovdal 2009-08-18 18:04:35

5

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

为C字符串的正则表达式:

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

的正则表达式是不是太难理解了。基本上文字串是一对周围一堆双引号:

  • 非特殊(非报价/反斜杠/换行符)字符
  • 逃逸,其以反斜杠开始,然后由一个的:
    • 一个简单的换码字符
    • 1至3个八进制数字
    • x和1个或多个十六进制数字

这是基于6.1.4和6.1.3节。4的C89/C90规范。如果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 literal正则表达式与字符串文字非常相似。

+0

在这种情况下,我认为它会更好:([^“\\\ n] | \\。)* – hiena 2009-08-18 15:53:07

+0

您的正则表达式无法处理 << char * str =”one \ two \ three \ n “; >>表示有一个换行符,这就是我的意思:) – hlovdal 2009-08-18 16:05:34

+0

使用\连接行是预处理的一部分,我忽略了它(例如:如果代码是< > - 你想怎么做?)如果你关心的只是连接线,你可以在abfnrtv字符类中添加\ n,并用sys替换for-loop .stdout.write(regex.sub(repl,sys.stdin.read())。你还需要调整chr_re,如果你担心char文字内部的行连接。 – 2009-08-18 16:20:21

0

在红宝石:

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

打印到标准输出

0

在Python使用pyparsing:

from pyparsing import dblQuotedString 

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

同时打印到标准输出。