我正在寻找一种在项目的C / C ++代码中搜索给定术语的方法,同时忽略注释和字符串中的任何出现。
由于代码库相当大,我正在寻找一种方法自动识别与我的搜索词匹配的代码行,因为它们需要手动检查。
如果可能,我想在我的linux系统上执行搜索。
有问题的代码库是一个带有大量第三方插件的实时信号处理引擎。插件是用各种语言实现的(主要是C语言,还有C ++和其他语言;目前我只关心这两种语言),没有执行任何标准。
我们的代码库目前使用内置类型float
作为浮点数,我们希望将其替换为允许我们使用双精度的typedef
。
我们希望在实际代码中找到float
的所有匹配项(忽略评论和打印输出中的合法用法)。
更进一步的是,在代码有效负载中有float
的某些(虽然很少)合法使用(所以我们真的在寻找一种方法来识别所有的地方需要手动检查,而不是运行一些自动搜索和替换。)
代码还包含到(float)
的C样式静态强制转换,因此依靠编译器警告来识别类型不匹配通常不是一种选择。
代码库包含超过3000个(C和C ++)文件,累积约750000行代码。
代码是跨平台的(linux,osx,w32是主要目标;但也是freebsd和类似的),并使用各种本机编译器(gcc / g ++,clang / clang ++,VisualStudio,...)进行编译
grep "\bfloat\b" | sed -e 's|//.*||' -e 's|"[^"]*"||g' | grep "\bfloat\b"
但我认为必须是搜索有效负载代码的更好方法。
答案 0 :(得分:5)
恕我直言,在“Unix& Linux”上的类似问题上有一个很好的答案:
grep适用于纯文本,并且对此没有任何了解 C程序的基础语法。因此,为了不搜索 在评论中你有几个选择:
在搜索之前删除C-comments,您可以使用gcc执行此操作 -fpreprocessed -dD -E yourfile.c有关详细信息,请参阅Remove comments from C/C++ code
编写/使用您已经找到的一些hacky半工作脚本 (例如,他们通过跳过以//或/ *开头的行来工作) 处理所有可能的C / C ++注释的细节(再次,请参阅 一些可怕的测试用例的上一个链接)。然后你仍然可能有假 积极的,但你不必预先处理任何事情。
- 醇>
使用更高级的工具在代码中进行“语义搜索”。一世 找到了“coccigrep”:http://home.regit.org/software/coccigrep/这个 一种工具允许搜索某些特定的语言语句 (即更新具有给定名称的结构),当然也就是他们 删除评论。
https://unix.stackexchange.com/a/33136/158220
虽然它并没有完全涵盖你的“不在字符串”的要求。
答案 1 :(得分:3)
它实际上可能取决于代码库的大小,也可能取决于您通常使用的编辑器。我建议使用GNU emacs(如果可能的话,在Linux上使用最近的GCC编译器...)
对于中小型代码(例如小于300KLOC),我建议使用Emacs的grep
mode。然后(假设您已将next-error
Emacs函数绑定到某个键,可能是(global-set-key [f10] 'next-error)
中的~/.emacs
...),您可以快速扫描float
的每次出现(偶数)在字符串或注释中,但你会很快跳过这样的事情......)。几个小时后,您将完成中等大小的源代码(这比学习如何使用新工具更快)。
对于大型代码(数百万行),可能需要自定义一些静态分析工具或编译器。您可以使用GCC MELT在Linux上自定义GCC编译器。其findgimple
mode可能具有启发性,甚至可能非常有用(您可能希望找到针对float
的所有Gimple分配)
float
取代double
类型的所有次出现 - 但只有大多数1>}(可能适当{{} 1}} - ed ...),因为很可能你正在使用一些外部(或标准)函数需要一个typedef
。
CADNA工具可能也很有用,可以帮助您估算结果的精确度(这样可以帮助您决定何时使用float
是合理的)。
使用GCC MELT中提到的CADNA,Coccinelle,Frama-C,Fluctuat(或许Coccigrep或g0hl1n's answer等语义工具}}会给出更精确或相关的结果,代价是花费更多时间(可能是几天!)来学习和定制工具。
答案 2 :(得分:1)
执行此操作的有效方法应该是EMP_ID FIRSTNAME LASTNAME SALARY ADDRESS_ID START_DATE END_DATE
1 Bob Way 55000 6 2010-06-10-12:00 2010-06-10-12:03
null Bob Way 50000 6 2010-06-10-12:03 null
(http://cscope.sourceforge.net/)使用cscope
选项的面向行的模式,但我还没有在各种各样的C标准,如果这对您不起作用,或者如果您无法获得find this C symbol
,请执行以下操作:
cscope
第一个find . -type f -print |
while IFS= read -r file
do
sed 's/a/aA/g;s/__/aB/g;s/#/aC/g' "$file" |
gcc -P -E - |
sed 's/aC/#/g;s/aB/__/g;s/aA/a/g' |
awk -v file="$file" -v OFS=': ' '/\<float\>/{print file, $0}'
done
替换所有带有唯一标识符字符串的哈希(sed
)和#
符号,以便预处理器不会对#include进行任何扩展等。但我们可以在预处理后恢复它们。
__
预处理输出以删除注释。
第二个gcc
替换了我们之前使用实际哈希符号添加的哈希标识符字符串。
sed
实际上在单词边界内搜索awk
,如果找到则打印文件名加上找到的行。这使用GNU awk作为单词边界float
和\<
。
第二个sed的工作可以作为awk命令的一部分完成,但我喜欢2个seds的对称性。
与使用\>
不同,这种sed / gcc / sed / awk方法不会避免在字符串中找到错误的匹配,但希望其中只有很少一些,你可以将它们排除在后无论如何都要手动处理。
它不适用于包含换行符的文件名 - 如果你有那些你可以但脚本中的正文,并将其作为cscope
执行。
通过添加您正在使用的任何C或C ++版本来修改gcc命令行,例如: find .. -print0 | xargs -0 script
。