我搜索了一种在源代码上进行 grep 的方法,而不会因为注释而有时出现误报。例如,如果我在此 .c 源代码上搜索 foo :
/*
* foo has changed [...] and is now a 2-parameters function
*/
// foo(24)
foo(42, 28);
天真的人grep
会发现 3 次出现,而我只想要 1 次。我见过这边走在 StackOverflow 上执行此操作,但它不能满足我的需求:PHP 在该平台上不可用。我也发现了这边走对于一行评论,但它只解决了我的问题的一部分。
我需要使用经典的脚本工具(awk、sed、bash、grep 等),并且我需要它快速地即使有数千个文件。
您现在知道是否以及如何可以对源代码进行 grep,并且只能对源代码进行 grep 吗?
答案1
grep 适用于纯文本,并且不了解 C 程序的底层语法。因此,为了不搜索内部评论,您有多种选择:
在搜索之前剥离 C 注释,您可以使用以下命令执行此操作。
gcc -fpreprocessed -dD -E yourfile.c
详细信息请参见https://stackoverflow.com/questions/2394017/remove-comments-from-cc-code编写/使用一些像您已经发现的半工作脚本(例如,它们通过跳过以
//
或开头的行来工作/*
),以便处理所有可能的 C/C++ 注释的详细信息(再次,请参阅前面的链接以获取一些可怕的测试用例) 。那么您仍然可能会出现误报,但您不必进行任何预处理。使用更高级的工具在代码中进行“语义搜索”。我找到了“coccigrep”:http://home.regit.org/software/coccigrep/这种工具允许搜索某些特定的语言语句(即具有给定名称的结构的更新),当然它们会删除注释。
答案2
您可以尝试一种简单的方法来匹配非注释,如下所示:
$ egrep -v "^(//|/\*| \*)" sourcecode
这只会与前缀注释反向匹配 - 即以//
, /*
,*
或开头的行*/
- 因此它不会遗漏用/*
和 对注释掉的块*/
。
答案3
对于我们这些后来才回答这个问题的人来说,这是一个具体的变体:
ls -1 src/*.c | xargs -i sh -c "echo;gcc -fpreprocessed -dD -E {} 2>&1 | grep -wi -e one -e two -e three -n | sed 's:^:{}\::'" | cat -s
C 源文件列表
ls -1 src/*.c
通过管道传输到 xargs,它在子 shell 中执行预处理器
gcc -fpreprocessed -dD -E {} 2>&1
随后通过管道输送到所需的 grep 命令中
grep -wi -e one -e two -e three -n
然后通过管道传输到 sed 中,以当前文件名作为每行的前缀
sed 's:^:{}\::'
最后,使用 cat 将所有重复的空白行折叠为单行:
cat -s
这适用于 RHEL6 系统,但我认为它对于其他 *nix 系统来说已经足够通用了。