如何在源代码中查找搜索词
how to find a search term in source code
我正在寻找一种在项目的C/C++代码中搜索给定术语的方法,同时忽略注释和字符串中的任何出现。
由于代码库相当大,我正在寻找一种方法来自动识别与我的搜索词匹配的代码行,因为它们需要手动检查。
如果可能的话,我想在我的 linux 系统上执行搜索。
背景
有问题的代码库是一个实时信号处理引擎,具有大量的第三方插件。 插件以多种语言实现(主要是 C,但也包括 C++ 和其他语言;目前我只关心这两种语言),没有强制执行任何标准。
我们的代码库目前使用内置的浮点数类型 float
,我们希望将其替换为允许我们使用双精度的typedef
。我们希望在实际代码中找到所有出现的float
(忽略注释和打印输出中的合法使用)。
更复杂的是,在代码有效负载中有一些(尽管很少)合法使用float
(所以我们真的在寻找一种方法来识别所有需要手动检查的地方,而不是运行一些自动搜索和替换。
代码还包含C风格的静态强制转换来(float)
,因此依靠编译器警告来识别类型不匹配通常不是一种选择。
代码库由 3000 多个(C 和 C++)文件组成,累积了大约 750000 行代码。
代码是跨平台的(Linux,OSX,W32是主要目标;还有FreeBSD和类似),并使用各种本机编译器(gcc/g ++,clan/clang++,VisualStudio,...)编译。
迄今。。。
到目前为止,我正在使用一些丑陋的东西,例如:
grep "bfloatb" | sed -e 's|//.*||' -e 's|"[^"]*"||g' | grep "bfloatb"
但我认为必须有一些更好的方法来仅搜索有效负载代码。
恕我直言,在"Unix和Linux"中有一个类似的问题有一个很好的答案:
grep 在纯文本上工作,对 C 程序的基础语法。因此,为了不搜索 在评论中,您有以下几种选择:
在搜索之前去除C注释,您可以使用gcc执行此操作 -fpreprocessing -dD -E yourfile.c 有关详细信息,请参阅从 C/C++ 代码中删除注释
编写/使用一些像你已经发现的笨拙的半工作脚本 (例如,它们通过跳过以//或/* 开头的行来工作,以便 处理所有可能的 C/C++ 注释的详细信息(再次请参阅 一些可怕的测试用例的上一个链接)。那么你仍然可能有假的 积极因素,但您不必预处理任何东西。
使用更高级的工具在代码中执行"语义搜索"。我 发现了"coccigrep":http://home.regit.org/software/coccigrep/这个 允许搜索某些特定语言语句的工具类型 (即具有给定名称的结构的更新),当然还有它们 删除评论。
https://unix.stackexchange.com/a/33136/158220
虽然它不能完全涵盖您的"非字符串"要求。
它实际上可能取决于您的代码库的大小,也可能取决于您通常使用的编辑器。我建议使用GNU emacs(如果可能的话,在Linux上使用最新的GCC编译器......)
对于中小型代码(例如小于 300KLOC),我建议使用 Emacs 的grep
模式。然后(假设你已经将 next-error
Emacs 函数绑定到某个键,也许在你的~/.emacs
中(global-set-key [f10] 'next-error)
......)你可以快速扫描float
的每一个出现(甚至在字符串或注释中,但你会很快跳过这样的出现......在几个小时内,您将完成中等大小的源代码(这比学习如何使用新工具更快)。
对于大型代码(数百万行),自定义一些静态分析工具或编译器可能是值得的。您可以使用GCC MELT在Linux上自定义GCC编译器。它的findgimple
模式可能是鼓舞人心的,甚至可能有用(您可能想找到针对float
的所有 Gimple 任务)
顺便说一句,您可能不想用 double
(可能适合typedef
-ed...)替换 float
类型的所有出现 - 但只替换其中的大部分 - 因为很可能您正在使用一些需要float
的外部(或标准)函数。
CADNA 工具也可能很有用,可以帮助您估计结果的精度(因此可以帮助您决定何时使用double
是明智的)。
使用语义工具,如GCC MELT,CADNA,Coccinelle,Frama-C(或者可能是Fluctuat,或g0hl1n的答案中提到的Coccigrep)将给出更精确或相关的结果,代价是不得不花费更多时间(也许是几天!)来学习和定制工具。
执行此操作的可靠方法应该是使用 find this C symbol
选项在面向行的模式下使用 cscope
(http://cscope.sourceforge.net/),但我还没有在各种 C 标准上使用它,所以如果这对您不起作用或者您无法获得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
实际上在单词边界内搜索float
,如果找到,则打印文件名以及找到它的行。这使用 GNU awk 表示词边界<
和>
。
第二个 sed 的工作可以作为 awk 命令的一部分完成,但我喜欢 2 个 sed 的对称性。
与使用 cscope
不同,这种 sed/gcc/sed/awk 方法不会避免在字符串中找到错误的匹配项,但希望这些匹配很少,无论如何,您可以在手动后处理时将它们清除。
它不适用于包含换行符的文件名 - 如果您有换行符,您可以将正文放入脚本中并按find .. -print0 | xargs -0 script
执行。
通过添加您正在使用的任何 C 或 C++ 版本来修改 gcc 命令行,例如 -ansi
.
- 查找存储在二叉搜索树的所有非叶子中的数据总和?(返回整数的独立递归函数
- 通过搜索硬盘驱动器查找文件目录
- 查找函数在unordered_map中的工作方式是搜索键值
- 我将如何搜索这个包含数组的文件以查找剩余的任何船只?
- 在二叉搜索树中查找元素
- 二进制搜索不变以查找元素的首次出现
- 使用二叉搜索查找数字的第 N 次出现的索引
- 使用 bin 搜索查找排序数组的模式
- 在二叉搜索树中查找最小和的算法改进
- 二叉搜索树查找和删除 [C++]
- C++通过windows搜索路径查找可执行文件
- 我们可以使用异构查找比较器对 STL 关联容器执行"partial-match"搜索吗?
- 使用递归在二进制搜索树中查找固定后继
- 单词搜索难题:如何搜索一系列字母来查找单词
- STL 设置::查找重新定义的搜索
- STD :: MAP-如何查找或添加,然后可以在一次搜索中删除项目
- 查找符号时,程序不会从正确的库中搜索
- 如何在二叉搜索树中查找元素
- 具有非常快速的内>数据查找和快速反向查找(搜索/插入/删除数据)的压缩字典?
- 如何在源代码中查找搜索词