如何在 Perl 代码集中找到包含特定字符串的所有方法? [英] How can I find all the methods that contain a specific string within a Perl codeset?

查看:41
本文介绍了如何在 Perl 代码集中找到包含特定字符串的所有方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我接到了一项棘手的任务,即在超过百万行的大型代码库中的某些点编写日志条目.

I've been given a tricky task which is to write a log entry at certain points within a large million+ line code base.

我需要记录的点可以从 500 多个模板类型的列表中找到.模板类型只是一个字符串,如end_assignment_affiliate"或interview_accepted".

The points that I need to log can be found from a list of 500+ template types. A template type is simply a string like "end_assignment_affiliate" or "interview_accepted".

我正在尝试编写一个 perl 脚本,该脚本将获取 500 个模板的列表,然后搜索代码以找到使用每个特定模板字符串的方法(然后我希望使用列表为每个模板类型找到进入系统的所有入口点的方法).

I'm trying to work out how to write a perl script that will take the list of 500 templates and then search through the code to find the methods that make use of each specific template string (I then hope to use the list of methods to find all the entry points into the system for each template type).

例如我可能有

sub aSub {
 my($arg) = @_
 ...
 if ($template eq 'interview_accepted') {
 ...
}

我想确定方法aSub 包含interview_accepted.Interview_accepted 可能包含在多个子程序中.

I want to determine that method aSub contains interview_accepted. interview_accepted may be contained within multiple subroutines.

grep 消息类型的代码库并在存在该消息的文件中找到行号非常容易,但是我很难识别包含方法.

It's quite easy to grep the code base for the message type and find the line number in files where that message exists, however I'm having a hard time trying to identify the containing method.

很明显,如果我能以编程方式执行此操作,它将更加健壮、可重复且速度更快.

Clearly if I can do this programmatically it will be more robust, repeatable and much quicker.

有谁知道我可以用来实现这一目标的任何模块或技巧吗?

Does anyone know of any modules or tricks that I can use to achieve this?

我目前正在使用 File::ReadBackwards 来查找字符串,然后从该点找到第一个子 [名称] { 点.我想知道是否有更优雅的解决方案?

I'm currently playing with using File::ReadBackwards to find the string, and then from that point find the first sub [name] { point. I'm wondering though if there is a more elegant solution?

推荐答案

我的 CPAN 模块 Devel::Examine::Subs 可以使用 has() 方法或函数来做到这一点.这是一个使用 OO 版本的示例脚本,它可以满足您的需求.只需输入要搜索(递归)的目录作为参数一,搜索词作为参数二:

My CPAN module Devel::Examine::Subs can do this with the has() method or function. Here's a sample script using the OO version, which will do what you want. Just enter the directory you want to search (recursively) as argument one, and the search term as argument two:

#!/usr/bin/perl
use warnings;
use strict;
use 5.18.0;

use Devel::Examine::Subs;
use File::Find;

my $des = Devel::Examine::Subs->new();

my $dir = $ARGV[0];
my $search = $ARGV[1];

find({ wanted => \&check_subs, no_chdir => 1 }, 
       $dir,
);

sub check_subs {

    if (! -f or ! /(?:\.pm|\.pl)$/){
        return;
    } 

    my $file = "$File::Find::name";

    my @has = $des->has({file => $file, search => $search});

    return if ! @has;

    say "\n$file:" ;
    say "\t$_" for @has;
}

像这样调用 perl des.pl business-isp/template 导致此示例输出:

Called like this perl des.pl business-isp/ template results in this example output:

business-isp/lib/Business/ISP/Reports.pm:
    income_by_item
    renewal_notices

business-isp/lib/Business/ISP/GUI/Accounting.pm:
    _display_plan_stats
    process_renew
    display_add_plan
    email_invoice
    process_purchase
    display_payment_form
    client_delete
    _contact_info_table
    show_plan
    display_uledger
    add_plan

business-isp/lib/Business/ISP/GUI/Base.pm:
    start
    _header
    display_config
    _render_error
    _blank_header
    _footer

更新:我稍微修改了脚本,以便它可以在带有一堆搜索词的循环中使用.只需将您的模板名称填充到 @searches 数组中,并在 $dir 中指定要搜索的目录结构.

UPDATE: I've modified the script slightly so it can be used in a loop with a bunch of search terms. Just populate your template names into the @searches array, and specify the directory structure to search in $dir.

#!/usr/bin/perl
use warnings;
use strict;
use 5.18.0;

use Devel::Examine::Subs;
use File::Find;

my $des = Devel::Examine::Subs->new();

my $dir = 'business-isp/';
my @searches = qw(template this that other);

for my $search (@searches){

    say "\n***** SEARCHING FOR: $search *****\n";

    find({ wanted => sub { check_subs($search) }, no_chdir => 1 }, 
           $dir
    );
}

sub check_subs {

    my $search = shift;

    if (! -f or ! /(?:\.pm|\.pl)$/){
        return;
    } 

    my $file = "$File::Find::name";

    my @has = $des->has({file => $file, search => $search});

    return if ! @has;

    say "\n$file:" ;
    say "\t$_" for @has;
}

更新:这是一个使用带有 lines 参数集的新 has() 方法的脚本.它检索搜索命中的整行,以及它所在的行号:

UPDATE: Here's a script that uses the new has() method with the lines parameter set. It retrieves the entire line that the search hits, along with the line number it's on:

#!/usr/bin/perl
use warnings;
use strict;
use 5.18.0;

use Devel::Examine::Subs;
use File::Find;

my $des = Devel::Examine::Subs->new();

my $dir = 'business-isp/';
my @searches = qw(date);

for my $search (@searches){

    say "\n***** SEARCHING FOR: $search *****\n";

    find({ wanted => sub { check_subs($search) }, no_chdir => 1 }, 
           $dir
    );
}

sub check_subs {

    my $search = shift;

    if (! -f or ! /(?:\.pm|\.pl)$/){
        return;
    } 

    my $file = "$File::Find::name";


    my %subs = $des->has({file => $file, search => $search, lines => 1});

    return if not %subs;

    print "\n$file:\n\n";

    for my $sub (keys %subs){    

        print "$sub:\n";

        for my $line_info (@{$subs{$sub}}){
            while (my ($k, $v) = each (%$line_info)){ 
                print "\tLine num: $k, Line Data: $v\n";
            }
        }
    }
}

输出:

business-isp/lib/Business/ISP/Sanity.pm:

validate_data:
    Line num: 168, Line Data:  $self->validate_value({ 
audit:
    Line num: 72, Line Data:  my $date = $self->date({ get => $schedule }); 
    Line num: 77, Line Data:  # update the audit list if the process is claiming to be 
    Line num: 86, Line Data:  date => $self->date({ get => 'day' }), 
    Line num: 108, Line Data:  date => { -like => "$date%" }, 
    Line num: 123, Line Data:  my $executed_date = $executed->date; 
    Line num: 126, Line Data:  "Process $process has already run its $schedule cycle on $executed_date"; 
validate_renew:
    Line num: 304, Line Data:  $self->validate_value({ 
validate_value:
    Line num: 193, Line Data:  # return if validate_value is disabled! 
    Line num: 204, Line Data:  print "Sanity validate_value_debug: $tag, $value\n"; 

business-isp/lib/Business/ISP/GUI/Accounting.pm:

confirm_payment:
    Line num: 1312, Line Data:  my $date = $self->string_date(); 
    Line num: 1316, Line Data:  $self->pb_param( date => $date ); 
display_invoice:
    Line num: 1867, Line Data:  my $date = $invoice->[0]->{ date }; 
    Line num: 1928, Line Data:  $template->param( date => $date ); 

这篇关于如何在 Perl 代码集中找到包含特定字符串的所有方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆