Bash脚本中使用Perl

时间:2015-09-06 06:26:13

标签: bash perl shell

我正在尝试编写一个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.ccat ${file}我得到类似类型的垃圾输出。是什么造成的?我有一种感觉,这是因为多行注释包含/ *,在Unix中是'根目录中的所有内容',但有没有办法解决这个问题?

编辑:在终端中运行perl命令perl -lne 'print if (/\/\*/ .. /\*\//)' main.c输出预期结果。

1 个答案:

答案 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的那个很低。如果您正在使用范围运算符..,请小心并在正确的位置使用大量括号。