learningperl01 has asked for the wisdom of the Perl Monks concerning the following question:

Hello everyone,
Hoping someone can help me/point me in the right direction with the following problem. I am using the following code to search for a bunch of regex's/strings then print which matches came from which headers (headers in this case defined by the lines that start with ***\s). Below is the code that I am using along with the output that I am currently seeing.
#!/usr/bin/perl use strict; use warnings; my %header = (); my $within_body = ''; my @search_strings = qw(stringa stringb stringc); while (<DATA>) { chomp; if ($_ =~ /^\*{3} (.+?)$/) { $within_body = $1; } else { foreach my $search_strings (@search_strings) { if (/$search_strings/) { push (@{$header{$within_body}}, $search_strings); } } } } foreach my $section (sort keys %header) { print "Found the following strings within body *** $section\n"; print join("\n", @{$header{$section}}); print "\n"; } __DATA__ *** 3993.2399 stringa stringb stringc *** 3993.23384j stringc junk data junk data *** 3993.23993k stringa stringb junk data junk data
The script print out and matches what I want for the most part. The problem is that I want to do if statements for each of the regexes that match and print a different message depending on which regex matched instead of just printing the name of the regex that matched. Sample code below of what I am trying to do. I am not quite sure to search/match the values stored in @{$header{$section}} and then printing the results based off the match.
if ( @{$header{$section}} = /stringa/gm ) { print "matched on stringa\n"; } if ( @{$header{$section}} = /stringb/gm ) { print "regex on string b\n"; } if ( @{$header{$section}} = /stringc/gm ) { print "C match\n"; }
CURRENT OUTPUT
Found the following strings within body *** 3993.23384j stringc Found the following strings within body *** 3993.2399 stringa stringb stringc Found the following strings within body *** 3993.23993k stringa stringb
DESIRED OUTPUT
Found the following strings within body *** 3993.23384j C match Found the following strings within body *** 3993.2399 matched on stringa regex on string b C match Found the following strings within body *** 3993.23993k matched on stringa regex on string b

Replies are listed 'Best First'.
Re: Regex matching against hash values
by ikegami (Patriarch) on Jun 17, 2009 at 18:43 UTC
    my %searchs = ( stringa => sub { print "matched on stringa\n"; }, stringb => sub { print "regex on string b\n"; }, stringc => sub { print "C match\n"; }, ); my %compiled = map { $_ => qr/\Q$_/ } keys %searchs ; while (<DATA>) { chomp; if (/^\*{3} (.+)/) { print "Found the following strings within body $1\n"; next; } for my $search_string (keys %searchs) { if (/$compiled{ $search_string }/) { $searches{ $search_string }->(); } } }

    You're not very clear on why you don't just do

    while (<DATA>) { chomp; if (/^\*{3} (.+)/) { print "Found the following strings within body $1\n"; next; } /patterna/ && print "matched on stringa\n"; /patternb/ && print "regex on string b\n"; /patternc/ && print "C match\n"; }

    Additional notes:

    • if (/.../g) is virtually always wrong.
    • You said your array contained strings which I take to mean arbitrary text, but you treat them as regular expression patterns. Fixed with \Q above.
    • You are recompiling the same regex patterns over and over again. I made changes to compile them only once each.