grep 正则表达式以避免在末尾匹配分号

grep 正则表达式以避免在末尾匹配分号

我想找到文件中以“_DB”结尾的所有函数声明,并避免perl和管道。

例如:

prep_DB();

init_DB(DB *database, char *params[])
{
  open_DB(database);
}

prep_DB() {
  open_DB(database); // open
}

FILE * load_DB(const char * exppath, const char * expfname)
{}

应该只匹配第二行和倒数第二行。该线prep_DB() {可以存在或不存在。

目前,以下命令可查找所有函数调用:

grep -E '.*_DB(.*)' file

然而,我在否定最后的分号时遇到了麻烦。最接近解释其工作原理的线程是;然而,分号似乎是一个特殊字符,因为那里的建议不起作用。我怎样才能绕过这个限制?

答案1

假设这是一个名为file.c.

使用ctags

$ ctags file.c

这将创建一个名为的文件tags

$ cat tags
init_DB file.c  /^init_DB(DB *database, char *params[])$/
load_DB file.c  /^FILE * load_DB(const char * exppath, const char * /
prep_DB file.c  /^prep_DB() {$/

这可以与函数定义一起使用vivim自动跳转到函数定义。

您还可以使用cutand解析此文件grep

$ cut -f 1 tags | grep '_DB$'
init_DB
load_DB
prep_DB

在 Ubuntu 系统上,安装ctags实际上会exuberant-ctags提供更详细的tags输出:

$ cat tags
!_TAG_FILE_FORMAT       2       /extended format; --format=1 will not append ;" to lines/
!_TAG_FILE_SORTED       1       /0=unsorted, 1=sorted, 2=foldcase/
!_TAG_PROGRAM_AUTHOR    Darren Hiebert  /[email protected]/
!_TAG_PROGRAM_NAME      Exuberant Ctags //
!_TAG_PROGRAM_URL       http://ctags.sourceforge.net    /official site/
!_TAG_PROGRAM_VERSION   5.9~svn20110310 //
init_DB file.c  /^init_DB(DB *database, char *params[])$/;"     f
load_DB file.c  /^FILE * load_DB(const char * exppath, const char * expfname)$/;"       f
prep_DB file.c  /^prep_DB() {$/;"       f

在这里我们可以确保只获得函数定义

$ awk '$NF == "f" && $1 ~ /_DB$/ { print $1 }' tags
init_DB
load_DB
prep_DB

这里的要点是,最好使用专用的 C 语言解析器,而不是尝试在解析 C 代码的awk脚本或正则表达式中考虑所有可能的编程风格。grep

你也可以做

$ ctags -x file.c
init_DB          function      3 file.c           init_DB(DB *database, char *params[])
load_DB          function     12 file.c           FILE * load_DB(const char * exppath, const char * expfname)
prep_DB          function      8 file.c           prep_DB() {

然后以您需要的任何方式解析/过滤它。该数字是定义的行号。这一切都取决于您所说的“想要找到”的含义。

答案2

我决定发布上面 20 多条评论讨论的摘要。

@don_crissti 提供了一种解决方案,他建议使用以下命令:

$ grep -E '.*_DB([^;]*)$' <filename>

产生输出

init_DB(DB *database, char *params[])
prep_DB() {
FILE * load_DB(const char * exppath, const char * expfname)

根据他的建议,如果需要,我想出了以下命令来排除中间结果:

$ grep -E '_DB\(.*\)$' <filename>

相关内容