哪些grep命令将在输出中包含当前函数名称?

| 我使用
-p
选项运行
diff
,因此输出将包括每次更改发生的函数的名称。
grep
有类似的选择吗?如果没有,我还可以使用其他什么命令? 我希望在匹配之前只显示一行具有最新功能签名的行,而不是用3来显示紧接在匹配之前的固定数量的上下文行,而在文件中却保留了很多行。如果我要查找的选项是
-p
,则输出可能看起来像这样,例如: $ cat foo.c int func1(int x,int y) {   返回x + y; } int func2(int x,int y,int z) {   int tmp = x + y;   tmp * = z;   返回tmp; } $ grep -p -n -e \'return \'foo.c 1-int函数1(int x,int y) 3:返回x + y; - 5-int func2(int x,int y,int z) 9:返回tmp;     
已邀请:
尽管过去已经讨论过,但GNU grep中没有这样的功能。 但是,如果您的代码受
git
的控制,则
git grep
可以选择
-p
。     
干得好:
git grep --no-index -n -p \'return\'
您只需要git。被搜索的文件不需要是git repo的一部分。 但是,如果是,则省略
--no-index
并获得即时速度提升!     
假设您正在搜索foobar:
grep -e \"^\\w.*[(]\" -e foobar *.h *.cpp | grep -B 1 foobar
对所有函数和所有foobar都进行摸索,然后仅对foobar和前几行进行摸索-这将仅仅是foobars和包含函数。 在Windows版本的cygwin上测试     
很不幸的是,不行。 feature2ѭ不存在此功能,
ack
不存在此功能(对improved2ѭ进行了改进)。 我确实希望这个存在。它会派上用场。有人确实在不久前实现了它,但是看起来好像他们的补丁从未被接受过(或者奇怪的是,甚至从未在线发布过)。您可以尝试通过电子邮件向他发送电子邮件,以查看他是否仍然有代码,并且仍然希望获得将C函数显示为
grep
的选项。 您可以编写一个正则表达式来匹配C函数,但是我敢打赌这将是一个正则表达式的庞然大物。     
我编写了一个脚本来grep C文件,并显示C函数名称和签名以及结果。 基于ctags。
#!/bin/bash

#
# grep_c_code
#
# Grep C files and print the results along with the function name and signature.
# Requires: ctags, gawk, sed, bash, and you probably want grep too.
#
# Written by David Stav, December 19 2012.
#
# Released to the public domain.
#

if [ $# -lt 2 ]; then
    echo \"Usage: $0 <grep_cmd> <files/dirs...>\" >&2
    echo \"\" >&2
    echo \"Example:\" >&2
    echo \"  $0 \'grep --color=always -n -e \\\"PATTERN\\\"\' file1 file2 dir1 dir2 | less -R\" >&2
    exit 1
fi

GREP_CMD=\"$1\"
shift

GAWK_SCRIPT=\"`
sed -n -e \'/^##### START of gawk script #####$/,/^##### END of gawk script #####$/p\' \\\"$0\\\" | \\
sed -n -e \'2,$ { $ D; p}\'
`\"

ctags -f - -R --sort=no -n --fields=+afikKmsSzt --extra=+fq \"$@\" | \\
gawk \"$GAWK_SCRIPT\" \"$GREP_CMD\" | \\
bash

exit 0

##### START of gawk script #####
function parse_line(a)
{
    a[\"tagname\"] = $1;
    a[\"filename\"] = $2;
    a[\"line_number\"] = gensub(/^([0-9]+).*$/, \"\\\\1\", 1, $3);
    if (a[\"line_number\"] == $3)
    {
        a[\"line_number\"] = \"0\";
    }
    a[\"kind\"] = gensub(/^.*\\tkind:([^\\t]+).*$/, \"\\\\1\", 1, $0);
    if (a[\"kind\"] == $0)
    {
        a[\"kind\"] = \"unknown kind\";
    }
    a[\"signature\"] = gensub(/^.*\\tsignature:(.*)$/, \"\\\\1\", 1, $0);
    if (a[\"signature\"] == $0)
    {
        a[\"signature\"] = \"\";
    }
}

function grep_section(a, next_line_number)
{
    printf(\"\\n\");
    printf(\"\\n\");
    printf(\"\\n\");
    printf(\"cat \'%s\' | \\\\\\n\", a[\"filename\"]);
    printf(\"sed -n -e \'%s,%sp\' | \\\\\\n\", a[\"line_number\"], next_line_number);
    printf(\"%s | \\\\\\n\", grep_cmd);
    printf(\"sed -e \'1 i \\\\\\n\");
    printf(\"\\\\n\\\\n\\\\n--\\\\\\n\");
    printf(\"[%s:%s]\\\\\\n\", a[\"filename\"], a[\"line_number\"]);
    printf(\"<%s> %s%s\\\\\\n\", a[\"kind\"], a[\"tagname\"], a[\"signature\"]);
    printf(\"\'\\n\");
}

BEGIN \\
{
    FS = \"\\t\";
    grep_cmd = ARGV[1];
    ARGV[1] = \"\"
}

!/^!/ \\
{
    parse_line(next_line);
    if (a[\"line_number\"])
    {
        next_line_number = next_line[\"line_number\"] - 1;
        grep_section(a, next_line_number);
        delete a;
    }
    for (key in next_line)
    {
        a[key] = next_line[key];
    }
}

END \\
{
    if (a[\"line_number\"])
    {
        next_line_number = \"$\";
        grep_section(a, next_line_number);
    }
}
##### END of gawk script #####
请享用。 :)     
与大多数文本处理操作一样,awk的作用很小:
$ awk -v re=\'return\' \'/^[[:alpha:]]/{f=FNR\"-\"$0} $0~re{printf \"%s\\n%d:%s\\n--\\n\",f,FNR,$0; f=\"\" }\' file
1-int func1(int x, int y)
3:  return x + y;
--
5-int func2(int x, int y, int z)
9:  return tmp;
--
上面假设函数签名是任何以字母(/ ^ [[:: alpha:]] /)开头的行。如果这不是编写代码的方式,请进行调整以适合您的情况。     
这是一个不完善的解决方案。它具有以下缺陷: 它需要一个名为
ctags
的工具 因此,它适用于C文件或ctags支持的任何语言,但不能超出此范围。 无论如何,它将显示所有C函数头。这是我脚本的最大问题,您也许可以找到一种解决方法。 我调用了脚本“ cgrep.sh \”,其语法如下:
cgrep.sh search-term files...
Cgrep.sh依靠ѭ17来工作,以生成函数头的搜索模式列表。然后,我们可以搜索函数头和搜索词。 事不宜迟,这里是cgrep.sh:
#!/bin/sh

# Grep, which includes C function headers
# cgrep term files*

TERM=$1                             # Save the search term
shift

ctags \"$@\"                          # produces the tags file
sed -i.bak \'s:^.*/^:^:;s:/$::\' tags # Prepare the tags file for grep
                                    # Original contents is backed up to tags.bak
grep -f tags -e $TERM \"$@\"          # Grep both headers and search term
rm tags tags.bak                    # Clean up
    
实际上,从我回想起的过去二十年来,“ grep -p”一直是AIX中的固定工具。它就在那里,这只是将行为移植到新代码中的问题。 但是,它很粗糙,可能需要帮助才能知道函数中的空行不计算在内。     
您可以编写一个脚本,将“ 21”放到一个临时文件中,然后再将其“ 22”放到一个临时文件中。这样,
diff
将找到
grep
删除的行(即所需的行),并且您将获得完全相同的函数匹配。     

要回复问题请先登录注册