我正在尝试编写一个Bash脚本,该脚本将在包含多个C源文件的文件夹中运行。其中一个将包含main(),并且还将在顶部包含一个描述文件/程序及其功能的多行注释。
到目前为止我所拥有的是:
#! /bin/bash
echo "Grepping for main *.c file"
file=$(grep -l main *.c)
echo "the file is ${file}"
comment=$(perl -lne 'print if (/\/\*/ .. /\*\//)' ${file})
echo ${comment}
它告诉我哪个文件包含main()(在测试用例中,它是main.c)。然后perl函数输出(我认为是)错误的。它不仅仅是在文件中搜索,而是输出
Grepping for main *.c file
the file is main.c
/$RECYCLE.BIN /Applications /Backup /Extra /Extra (from old Mac) 2 /Library /Network /OS X Install Data /System /System Volume Information /Users /Volumes /bin /boot CMakeLists.txt build comment.sh main.c main.dSYM makefile tasksheet.pdf Student Number: n9999999 CMakeLists.txt a1_n9999999 build comment.sh main.c main.dSYM makefile tasksheet.pdf...
后跟文件夹内容的标题,实际的多行注释分散在整个输出中。
如果我尝试cat main.c
它输出正确,但如果在bash脚本中我做回声cat main.c
或cat ${file}
我得到类似类型的垃圾输出。是什么造成的?我有一种感觉,这是因为多行注释包含/ *,在Unix中是'根目录中的所有内容',但有没有办法解决这个问题?
编辑:在终端中运行perl命令perl -lne 'print if (/\/\*/ .. /\*\//)' main.c
输出预期结果。
答案 0 :(得分:3)
你需要加倍引用回声:
echo "${comment}"
您看到/*
扩展到根目录中的文件列表。
(根目录中有很多碎片不应该存在。你不应该在/
目录中写文件。你需要担心你是怎样的(错误的)使用root权限。)
请注意,main
的测试不够灵敏。将匹配包含单词remaining或包含字母序列m-a-i-n的许多其他单词中的任何单词的文件。然而,这与手头的问题基本相关。
我对grep不是很好。关于如何使测试更加健壮的任何提示?
最基本的步骤是grep -l -w main
来搜索“main”这个词。然而,这将在评论中提到“主要想法是......”等等。我可能会利用main()
函数格式化知识,使用grep -l -E '^int main\((void|int argc, char \*\*argv)\)$
来获取int main(void)
或int main(int argc, char **argv)
- 它们是我用过的唯一签名,我将类型与函数保持在同一行。如果您将int
放在上一行,请从匹配项中删除int
;如果您在同一条线上有开放式大括号,请修改模式以允许或要求该布局;你可能仍会遇到“评论中的主要”问题,但这种可能性很小。
我还注意到Perl会在每个文件中拾取每个块注释,而不是在第一个文件结束时停止。大多数源文件中不应该只有一个注释。我想你可以解决这个问题:
perl -ne 'if (/\/\*/ .. /\*\//) { print if ($comment == 0); } ++$comment if m/\*\//;'
我尝试了一种更为紧凑的符号:
perl -lne 'print if (/\/\*/ .. /\*\// && $comment == 0); ++$comment if m/\*\//'
此主题和&& $comment == 0
条件的许多变体在功能上被忽略。上面显示的替代方案有效。
好奇心让我变得更好。使用'Deparse'模块(SO搜索'[perl] deparse
')并应用它显示:
$ perl -MO=Deparse -lne 'print if (/\/\*/ .. /\*\// && $comment == 0); ++$comment if m/\*\//'
BEGIN { $/ = "\n"; $\ = "\n"; }
LINE: while (defined($_ = <ARGV>)) {
chomp $_;
print $_ if m[/\*] .. m[\*/] && $comment == 0;
++$comment if m[\*/];
}
-e syntax OK
$ perl -MO=Deparse -lne 'print if ((/\/\*/ .. /\*\//) && $comment == 0); ++$comment if m/\*\//'
BEGIN { $/ = "\n"; $\ = "\n"; }
LINE: while (defined($_ = <ARGV>)) {
chomp $_;
print $_ if m[/\*] .. m[\*/] and $comment == 0;
++$comment if m[\*/];
}
-e syntax OK
$ perl -lne 'print if ((/\/\*/ .. /\*\//) && $comment == 0); ++$comment if m/\*\//' e2big.c
/* SO 18559403: How big an argument list is allowed */
$
&&
的优先级很高; and
的那个很低。如果您正在使用范围运算符..
,请小心并在正确的位置使用大量括号。