如何使用 shell 脚本提取给定 c/cpp 文件中的函数定义/内容?

如何使用 shell 脚本提取给定 c/cpp 文件中的函数定义/内容?

我挠了挠头才得到下面的结果。假设我有一个如下所示的 .c 文件:

file.c
int fun1()
{
  int x = 3;
  return x;}
void f2()
{
   int x= 7; 
   int y =0;
}

有人可以帮助如何仅获取函数名称和主体并将它们写入其他文件吗?我尝试了 ctags、grep 等。我只得到了函数名称,但没有得到正文

答案1

有人可以帮助如何仅获取函数名称和主体并将它们写入其他文件吗?我尝试了 ctags、grep 等。我只得到了函数名称,但没有得到正文

您需要真正理解语法的东西。 Grep 和 consorts 无法解析 C 或 C++(有正则表达式引擎可以解析的语言类型的数学描述,awk 等也是如此,C 不属于此类语言,而 C++ 更难)比 C 来解析)。

ctags是纯粹的 1990 年代初的技术(将其转化为自那时以来的 C 和 C++ 语言版本,您就会明白为什么今天依赖它是值得怀疑的)。大多数基于解析器的“启发式”实际上太简单而无法完全“理解”C 或 C++。另外,正如您所注意到的,关心了解在哪里一个符号是,而不是内容任何函数。 (我使用过 exuberant ctags,它的最后一个版本是 2009 年,所以不可能解析 C++11++ 或 C11++,但我听到了关于通用 ctags 的更好的事情,但这仍然是一个没有上下文的基于文本的工具信息,它无法处理多态性、跨文件模板以及基本上 C++ 2003 年后为中型到大型项目带来的所有好东西。)

因此,坏消息是您或多或少需要一个完整的 C 编译器(或完整的 C++ 编译器),减去机器语言的实际翻译。所以,你很可能永远无法自己写出效果很好的东西;一个团队的规模太小,无法实现如此复杂的语言。

好的消息是其他人已经发明了一般的使工具(如 IDE、linter、语法检查器...)能够访问相当强大的语言解析器的方法,并且有很多语言解析器可供选择,尤其是适用于 C++ 的语言解析器。
(我认为这两种截然不同的语言,C++ 是更难的一种,所以 C++ 支持是令人惊讶的;事实上,虽然 C 语法不是 C++ 的子集,但 C++ 的余数减法from C 足够小,您可以使用 C++ 解析器来获取 C 函数的内容,除非您确实要使用 ANSI 之前的 C 样式。)

有的是语言服务器协议(LSP),这就是 (neo)vim、emacs、Spyder、VSCode、Kate… 获得所有“跳转到声明”、“突出显示错误”、“显示内联定义”功能的方式:语言服务器使用 LSP 来了解它所看到的内容(clangd是 C++ 的首选 LSP 服务器)。

你也可以这样做! LSP 并不是一个复杂的协议。事实上,它只是一堆 JSON-RPC 请求(JSON-RPC:想想“REST”,但你使用的不是 HTTP,而是更简单的东西,而不是“一般,无论如何”,它始终是 JSON 作为负载)。因此,您可以找到一个 JSON-RPC 命令行客户端,clangd在脚本中手动启动并使用该 CLI 客户端向该客户端发出请求(使用 LSP 语言),或者您只需采用具有 CLI 界面的现有客户端并使用它。

考虑到客户端中肯定不喜欢复杂性,但需要解析 C++(和 C)的 LSP 服务器中的复杂性,自己编写客户端代码可能不会获得什么效率。因此,我只需将 neovim 或 emacs 推入后台/守护进程模式,并与它们的脚本接口交互(neovim:Lua,emacs:elisp)。

赌注你希望这就像跑步一样简单

cool_tool \
  -symbol-content "myns::containers::coolcont<Owlfeet>::hoot(int, int, std::string)" \
  -source-file owls.cc

并获取hoot函数的内容,但遗憾的是在 C++ 项目中,甚至要知道您的符号是如何形成的,哪个重载是在哪个文件中实现的,以及哪些东西甚至是某个函数的实现的候选者,您需要有一个概述所有软件模块的编译单元,包括等等。因此,如果您不将 C++ 解析器与如何编译的知识一起使用,您确实必须将 C++ 解析器视为一种失败的东西 - 这就是为什么 C++ LSP 工具通常很好地集成在 IDE 中,您无法仅调用几个文件来单独调用任何东西;很抱歉带来这种坏消息。中的大量工作在clangd内部使用 clang 编译器的语言理解,无需解析包含 1000 次的每个文件,即使它没有更改或不相关。

使用相当轻薄的 neovim 作为“可使用 CLI 的”IDE,一切都会好起来的。这并不是我可以推荐的真正有效的单一命令行工具。

一般来说,如果您正在处理 C 和 C++ 源代码等复杂数据,也许 shell 脚本根本不是您想要构建的工具。感觉像是一种非常不通用的语言来编写一些处理非常通用的语言的东西!

相关内容