我有一个像这样的长链if elsif块,其中我使用Capture::Tiny捕获命令的输出,然后使用一系列正则表达式将其提取。

sub capture_cpu_test {
    my ($cmd) = @_;
    print '--------------------', "\n";
    print 'COMMAND is: ', "$cmd", "\n";

    #capture an output of sysbench command
    my ( $stdout_to_format, $stderr, $exit ) = capture {
        system($cmd );
    };

    #split on newline to separately analyze later
    my @output_lines = split( "\n", $stdout_to_format );

    #set hash to collect param => param_value pairs
    my %plotting_hash = ();

    foreach my $line (@output_lines) {
        if ( $line =~ m/\ANumber\s+of\s+threads:\s+(\d+)\z/xms ) {
            $plotting_hash{num_threads}   = $1;
        }

        #long list of elseif continues

        elsif ( $line =~ m{\A\s+events\s+\(avg\/stddev\):\s+(.+?)\/(.+?)\z}xms ) {
            $plotting_hash{events_avg}    = $1;
            $plotting_hash{events_stddev} = $2;
        }
    }

    #returns ref to plotting_hash to combine upstream
    my $hash_plot_ref = \%plotting_hash;
    print 'Printing $hash_plot_ref inside capture_cpu_test: ', "\n";
    print Dumper($hash_plot_ref);
    return $hash_plot_ref;
}

我想使其更具可读性,所以我使用网络上的答案将此elsif块更改为调度表,没问题,它可以正常工作:
#set dispatch table with regex => sub {} pairs
my %plotting_hash  = ();
my %dispatch_regex = (
    qr/\ANumber\s+of\s+threads:\s+(\d+)\z/xms =>
      sub { $plotting_hash{num_threads}   = $1 },

    #more entries here

    qr{\A\s+events\s+\(avg\/stddev\):\s+(.+?)\/(.+?)\z}xms =>
      sub { $plotting_hash{events_avg}    = $1;
            $plotting_hash{events_stddev} = $2; },
);

#populate the %plotting_hash by calling dispatch table (%dispatch_regex)
my $code_ref;
foreach my $line (@output_lines) {
    foreach my $regex ( keys %dispatch_regex ) {
        if ( $line =~ $regex ) {
            $code_ref = $dispatch_regex{$regex};
            $code_ref->();
            last;
        }
    }
}

我得到这样的东西:
$hash_plot_ref = {
      'num_threads'         => '4',
      'events_stddev'       => '50.98',
      'events_avg'          => '2500.0000',
      ...
};
  • 我想知道这种从数据行正则表达式到匿名子例程的调度是如何工作的。捕获物($ 1,$ 2)如何转移到anon sub?这个匿名子如何精确获取参数?我试图用B::Deparse弄清楚它,但是并不能说明太多。
  • 我该如何使其更具可读性?我尝试使用列表式三元组以及for / when(此处未显示),但它看起来仍然不比链接elseif好得多。
  • 最佳答案

  • 我想知道这种从数据行正则表达式到匿名子例程的调度是如何工作的。捕获($ 1,$ 2)如何获得
    转移到匿名子?这个匿名子如何精确获取参数?一世
    试图用B::Deparse来解决这个问题,但是并不能说明太多。


  • $ 1和$ 2就像全局变量。它们随处可见。当执行以下代码行时:
    if ( $line =~ $regex ) {
    

    如果成功,则$ 1和$ 2等将具有该成功匹配中的值。顺便说一下,您知道
    (something)
    

    位由正则表达式引擎用来提供$ 1,$ 2等?


  • 我该如何使其更具可读性?我尝试了列表三元组和for / when(此处未显示),但看起来仍然不多
    比链式elseif好。


  • 实际上,一旦您了解发生了什么,那就还算不错。对我来说,我看到一个模式和一个相关的块。我喜欢。与分散在更多行上相比,各个部分之间的距离更近,并且更容易看到。给自己一些时间去理解,很快它将变得有意义。

    我不确定在不花时间思考的情况下对三元意味着什么-您真的要澄清吗?如果是这样,请发布一个新问题,或者向该问题添加更多信息,以便可以解决该问题。

    07-24 09:50
    查看更多