in reply to Assign regexp output to array not working
Output from running the program was:#!/usr/bin/perl use strict; use warnings; use Data::Dumper; use constant STATUS_COMPLETED_RE => qr{ ^string-here \s string-here: \s \((\w+)\) \s #alarm level ([\w|\s]+) \s completed, \s #job completed Total\s (\d+) \sclient\(s\), \s #total client +s ( #Details - (\d+) \s # number ([\w|\s\(\)]+) ,|\. # su +cceed,fail,etc. )* # any numbe +r of }xms ; my @sample_str = ('string-here string-here: (alarm_level_5) group5 com +pleted, Total 55 client(s),', 'string-here string-here: (alarm_level_2) group2 completed, To +tal 22 client(s), 422 succeed,622 fail,911 no_pass.'); my (@data, %stats); for my $line ( @sample_str ) { if (@data = ($line =~ STATUS_COMPLETED_RE )) { print Data::Dumper->Dump([\@data], [qw/*data/]); $stats{level} = shift @data; $stats{group} = shift @data; $stats{total} = shift @data; } else { print "No match\n"; } } print Data::Dumper->Dump([\%stats], [qw/*stats/]);
The first sample failed because of line:C:\perlp>perl try.pl No match @data = ( 'alarm_level_2', 'group2', '22', '622 fail,', '622', 'fail' ); %stats = ( 'group' => 'group2', 'level' => 'alarm_level_2', 'total' => '22' ); C:\perlp>C:\perlp>
In parsing the details section, notice from the output that @data, only picked up the second detail set.
It did this because it only captures the last successful match. First, it captured 422 succeed,, then 622 fail, and failed to match 922 no_pass (because the line doesn't end in a comma).
Also, it's capturing the whole detail section and the separate 2 items inside the details. I think what you mean (?) is to capture all the detail groups as a whole (i.e., 422, 622 and 911 and their status).
If thats what you mean, then this might be the code:
#!/usr/bin/perl use strict; use warnings; use Data::Dumper; use constant STATUS_COMPLETED_RE => qr{ ^string-here \s string-here: \s \((\w+)\) \s #alarm level ([\w\s]+) \s completed, \s #job completed Total\s (\d+) \sclient\(s\), \s? #total clien +ts ((?: #Details +- \d+ \s # number [\w\s\(\)]+ [,.] # succe +ed,fail,etc. )*) # any numbe +r of }xms ; my @sample_str = ('string-here string-here: (alarm_level_5) group5 com +pleted, Total 55 client(s),', 'string-here string-here: (alarm_level_2) group2 completed, To +tal 22 client(s), 422 succeed,622 fail,911 no_pass.'); my (@data, %stats); for my $line ( @sample_str ) { if (@data = ($line =~ STATUS_COMPLETED_RE )) { print Data::Dumper->Dump([\@data], [qw/*data/]); $stats{level} = shift @data; $stats{group} = shift @data; $stats{total} = shift @data; } else { print "No match\n"; } } print Data::Dumper->Dump([\%stats], [qw/*stats/]);
The output for this was:
Update: Here's another way to construct the regex which might be easier to read (from an example in 'Programming Perl', in the chapter Pattern Matching).C:\perlp>t1.pl @data = ( 'alarm_level_5', 'group5', '55', '' ); @data = ( 'alarm_level_2', 'group2', '22', '422 succeed,622 fail,911 no_pass.' ); %stats = ( 'group' => 'group2', 'level' => 'alarm_level_2', 'total' => '22' ); C:\perlp>
my $start = 'string-here string-here:'; my $level = '\((\w+)\)'; my $group = '([\w\s]+) completed,'; my $total = 'Total (\d+) client\(s\),'; # if there are details, they're captured in the end parens my $re = qr/^$start $level $group $total ?(.*)$/;
|
---|