Shell 哪个grep命令将在其输出中包含当前函数名?
我使用Shell 哪个grep命令将在其输出中包含当前函数名?,shell,grep,Shell,Grep,我使用-p选项运行diff,因此输出将包括发生每个更改的函数的名称。对于grep,是否有类似的选项?如果没有,我可以使用其他什么命令来代替 我不想在匹配之前显示固定数量的上下文行,而是希望在匹配之前只显示一行最新的函数签名,不管文件中有多少行。如果我要查找的选项是-p,则输出可能如下所示,例如: $ cat foo.c int func1(int x, int y) { return x + y; } int func2(int x, int y, int z) { int tmp =
-p
选项运行diff
,因此输出将包括发生每个更改的函数的名称。对于grep
,是否有类似的选项?如果没有,我可以使用其他什么命令来代替
我不想在匹配之前显示固定数量的上下文行,而是希望在匹配之前只显示一行最新的函数签名,不管文件中有多少行。如果我要查找的选项是-p
,则输出可能如下所示,例如:
$ cat foo.c
int func1(int x, int y)
{
return x + y;
}
int func2(int x, int y, int z)
{
int tmp = x + y;
tmp *= z;
return tmp;
}
$ grep -p -n -e 'return' foo.c
1-int func1(int x, int y)
3: return x + y;
--
5-int func2(int x, int y, int z)
9: return tmp;
$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-整数func1(整数x,整数y)
3:返回x+y;
--
5-整数func2(整数x,整数y,整数z)
9:返回tmp;
不幸的是,没有。此功能在
grep
中不存在,在ack
中也不存在(这是ab改进的grep
替换)
不过,我真的希望这个存在。它会派上用场的,但看起来他们的补丁从未被接受过(奇怪的是,甚至从未被发布到网上)。你可以试着给他发电子邮件,看看他是否还有代码,是否还想得到一个选项,在grep
中显示C函数
您可以编写一个正则表达式来匹配一个C函数,但我敢打赌这将是一个巨大的正则表达式。在GNU grep中没有这样的函数,尽管它已经在过去了
但是,如果您的代码在
git
的控制下,git grep
有一个选项-p
,可以做到这一点。这里有一个不完美的解决方案。它有以下缺陷:
ctags
cgrep.sh search-term files...
Cgrep.sh依靠ctags
生成函数头的搜索模式列表。然后,我们可以同时搜索函数头和搜索项。
不用多说,这里是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
假设您正在搜索foobar:
grep -e "^\w.*[(]" -e foobar *.h *.cpp | grep -B 1 foobar
greps表示所有函数和所有foobar,然后greps表示foobar和前面的行,这将只是foobar和包含函数
在windows版本的cygwin上测试时,我为grep C文件编写了一个脚本,并显示了C函数名和签名以及结果。 基于CTAG
#!/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 #####
#/bin/bash
#
#grep_c_代码
#
#Grep C文件并打印结果以及函数名和签名。
#需要:CTAG、gawk、sed、bash,您可能也需要grep。
#
#David Stav撰写,2012年12月19日。
#
#发布到公共领域。
#
如果[$#-lt 2];然后
回显“用法:$0”>&2
回显“”>&2
echo“示例:”>&2
echo“$0”grep--color=always-n-e\“PATTERN\”file1 file2 dir1 dir2 | less-R”>&2
出口1
fi
GREP_CMD=“$1”
转移
GAWK_脚本=”`
sed-n-e'/^^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^\
sed-n-e'2,${$D;p}'
`"
ctags-f--R--sort=no-n--fields=+afikKmsSzt--extra=+fq“$@”|\
gawk“$gawk_SCRIPT”“$GREP_CMD”|\
猛击
出口0
#####gawk脚本的开始#####
函数解析_行(a)
{
[“标记名”]=1美元;
a[“文件名”]=2美元;
a[“行号”]=gensub(/^([0-9]+).$/,“\\1”,1,$3);
如果(a[“行号”]==3美元)
{
a[“行号”]=“0”;
}
a[“种类”]=gensub(/^.*\tkind:([^\t]+).$/,“\\1”,1,$0);
如果(a[“种类”]==0美元)
{
a[“种类”]=“未知种类”;
}
a[“签名”]=gensub(/^.*\t签名:(.*)$/,“\\1”,1,$0);
如果(a[“签名”]==0美元)
{
a[“签名”]=“”;
}
}
函数grep_段(a,下一行编号)
{
printf(“\n”);
printf(“\n”);
printf(“\n”);
printf(“目录“%s”\\\n”,一个[“文件名]);
printf(“sed-n-e“%s,%sp'\\\n”,一个[“行号”],下一行号);
printf(“%s | \\\n”,grep\u cmd);
printf(“sed-e'1 i\\\n”);
printf(“\\n\\n\\n--\\n”);
printf(“[%s:%s]\\\n”、一个[“文件名”]、一个[“行号”]);
printf(“%s%s\\\n”、一个[“种类”]、一个[“标记名”]、一个[“签名”]);
printf(“'\n”);
}
开始\
{
FS=“\t”;
grep_cmd=ARGV[1];
ARGV[1]=“”
}
!/^!/ \
{
解析_行(下一个_行);
如果(a[“行号”])
{
下一行编号=下一行[“行编号”]-1;
grep_段(a,下一行编号);
删除一条;
}
用于(输入下一行)
{
a[键]=下一行[键];
}
}
结束\
{
如果(a[“行号”])
{
下一行\u编号=“$”;
grep_段(a,下一行编号);
}
}
#####目瞪口呆脚本结束#####
享受。:) 您可以将一个脚本
grep-v
s写入一个临时文件,然后diff-p
s与原始文件一起写入。这样diff
将找到grep
删除的行(即您想要的行),并且您将获得完全相同的函数匹配。与大多数文本处理操作一样,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:][]/)开头的任何行。如果您的代码不是这样编写的,只需调整以适应。事实上,“grep-p”在过去二十年中一直是AIX中的一个固定选项。它就在那里,只是将行为移植到新代码中的问题
不过,它很粗糙,可能需要帮助才能知道函数中的空行不算数。给你:
git grep --no-index -n -p 'return'
你只需要git。正在搜索的文件不需要是git repo的一部分。
但如果是,则省略--无索引,并获得即时速度