下面的脚本在文本文件中获取函数名称并在a上进行扫描 包含多个c,h文件的文件夹。它一个接一个地打开这些文件 读取每一行。如果在文件的任何部分中找到匹配项,则会打印出 行号和包含匹配的行。
除非比较不正常,否则一切正常。我会非常感谢能解决我问题的人。
#program starts:
use FileHandle;
print "ENTER THE PATH OF THE FILE THAT CONTAINS THE FUNCTIONS THAT YOU WANT TO
SEARCH: ";#getting the input file
our $input_path = <STDIN>;
$input_path =~ s/\s+$//;
open(FILE_R1,'<',"$input_path") || die "File open failed!";
print "ENTER THE PATH OF THE FUNCTION MODEL: ";#getting the folder path that
#contains multiple .c,.h files
our $model_path = <STDIN>;
$model_path =~ s/\s+$//;
our $last_dir = uc(substr ( $model_path,rindex( $model_path, "\\" ) +1 ));
our $output = $last_dir."_FUNC_file_names";
while(our $func_name_input = <FILE_R1> )#$func_name_input is the function name
#that is taken as the input
{
$func_name_input=reverse($func_name_input);
$func_name_input=substr($func_name_input,rindex($func_name_input,"\("+1);
$func_name_input=reverse($func_name_input);
$func_name_input=substr($func_name_input,index($func_name_input," ")+1);
#above 4 lines are func_name_input is choped and only part of the function
#name is taken.
opendir FUNC_MODEL,$model_path;
while (our $file = readdir(FUNC_MODEL))
{
next if($file !~ m/\.(c|h)/i);
find_func($file);
}
close(FUNC_MODEL);
}
sub find_func()
{
my $fh1 = FileHandle->new("$model_path//$file") or die "ERROR: $!";
while (!$fh1->eof())
{
my $func_name = $fh1->getline(); #getting the line
**if($func_name =~$func_name_input)**#problem here it does not take the
#match
{
next if($func_name=~m/^\s+/);
print "$.,$func_name\n";
}
}
}
答案 0 :(得分:2)
$func_name_input=substr($func_name_input,rindex($func_name_input,"\("+1);
你错过了一个结束括号。应该是:
$func_name_input=substr($func_name_input,rindex($func_name_input,"\(")+1);
这也可能比这四种陈述更容易。但是,把我的头脑包裹起来还有点早。你想在“function foo(){”中匹配“foo”吗?如果是这样,你可以使用像/ \ s +([^]] +)/。
这样的正则表达式当您说$func_name =~$func_name_input
时,您将$ func_name_input中的所有字符视为特殊的正则表达式字符。如果这不是您的意思,您可以使用quotemeta(perldoc -f quotemeta):$func_name =~quotemeta($func_name_input)
或$func_name =~ qr/\Q$func_name_input\E/
。
使用strictures(以及语法高亮显示编辑器)可以更轻松地进行调试。另请注意,如果您没有在其他文件中使用这些变量,“我们的”不执行任何“我的”不会对文件范围的变量执行任何操作。
答案 1 :(得分:1)
find + xargs + grep可以达到你想要的90%。
find . -name '*.[c|h]' | xargs grep -n your_pattern
ack更容易。
ack --type=cc your_pattern
只需从您的文件中获取您的模式列表,然后“或”将它们放在一起。
ack --type=cc 'foo|bar|baz'
这样做的好处是只搜索一次文件,而不是为你正在搜索的每个模式搜索一次。
答案 2 :(得分:1)
我仍然认为你应该使用ack,但你的代码需要一些严肃的爱。
这是您的程序的改进版本。它现在需要在命令行上搜索和模式的目录,而不是要求(和用户写入)文件。它使用File :: Find搜索目录下的所有文件,而不仅仅是目录中的文件。它通过将所有模式连接成正则表达式一次完成此操作。它使用正则表达式而不是index()和substr()以及reverse()和哦上帝。它只使用内置的文件句柄而不是FileHandle模块并检查eof()。一切都被声明为词汇(我的)而不是全局(我们的)。严格和警告正在进行,以便于调试。
#!/usr/bin/perl
use strict;
use warnings;
use File::Find;
die "Usage: search_directory function ...\n" unless @ARGV >= 2;
my $Search_Dir = shift;
my $Pattern = build_pattern(@ARGV);
find(
{
wanted => sub {
return unless $File::Find::name =~ m/\.(c|h)$/i;
find_func($File::Find::name, $pattern);
},
no_chdir => 1,
},
$Search_Dir
);
# Join all the function names into one pattern
sub build_pattern {
my @patterns;
for my $name (@_) {
# Turn foo() into foo. This replaces all that reverse() and rindex()
# and substr() stuff.
$name =~ s{\(.*}{};
# Use \Q to protect against regex metacharacters in the input
push @patterns, qr{\Q$name\E};
}
# Join them up into one pattern.
return join "|", @patterns;
}
sub find_func {
my( $file, $pattern ) = @_;
open(my $fh, "<", $file) or die "Can't open $file: $!";
while (my $line = <$fh>) {
# XXX not all functions are unindented, but your choice
next if $line =~ m/^\s+/;
print "$file:$.: $line" if $line =~ $pattern;
}
}