Refactored chained elsif (with regex) to send the table to Perl. But how does my code work?

I had a long if elsif coded block like this where I grab the output of a command using Capture :: Tiny and then extract it using a series of regexps.

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;
}

      

I wanted to make it more readable, so I changed this elsif block to mailing table using the answers on the net and no problem, it works:

#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;
        }
    }
}

      

I get something like this:

$hash_plot_ref = {
      'num_threads'         => '4',
      'events_stddev'       => '50.98',
      'events_avg'          => '2500.0000',
      ...
};

      

  • I would like to know how this dispatch works from a regex in a data string to an anonymous subroutine. How are the ($ 1, $ 2) captures passed to anon sub? How exactly do these advertisements get parameters? I tried to figure it out with B :: Deparse, but that says little.
  • How can I write it more readable? I've tried with tabbed tees and for / when (not shown here) and it still doesn't look much better than the elseif chain.
+3


source to share


1 answer


  • I would like to know how this dispatch works from a regex in a data string to an anonymous subroutine. How are captured ($ 1, $ 2) transferred to anon sub? How exactly do these advertisements get parameters? I tried to figure it out with B :: Deparse, but it says little.

$ 1 and $ 2 are like global variables. They are available everywhere. When the following line of code is executed:

if ( $line =~ $regex ) {

      

and if it succeeds, $ 1 and $ 2, etc. will have the values ​​from this successful match. By the way, you know that

(something)

      



the bit is used by the regex engine to feed $ 1, $ 2, etc.

  1. How can I write it more readable? I've tried with tabbed tees and for / when (not shown here) and it still doesn't look much better than elseif chaining.

Actually, once you understand what's going on, it's not too bad. For me, I can see the template and the block associated with it. I like this. The different parts are closer to each other and can be seen more easily than if they were distributed along more strict lines. Give yourself some time to understand and it will soon start to look meaningful.

I'm not sure what you mean about Trojans without wasting time thinking - do you really want to clarify? If so, please post a new question or add more information to this so that it can be reviewed.

+1


source







All Articles