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

Given:

my $left_text = [ qw{ when rome romans} ]; my $right_text = 'When in Rome, do as the Romans.'; # generate $regex and $flags somehow my $found = $right_text =~ m/$regex/$flags;

How do I $found == 3? How do I get from $left_text to $regex? What $flags?

Updates:

++ to all replies but the prize goes to AR for an especially compact solution.

Sorry; it's not clear to me what I want for various variations on the supplied data. I want to be able to tell, in a general way, whether lengthy text output is more or less as I expect. I will probably adopt AR's approach and tinker with the $left_text, accepting a certain degree of uncertainty.

- the lyf so short, the craft so long to lerne -

Replies are listed 'Best First'.
Re: Regex Find Words
by moritz (Cardinal) on Apr 29, 2010 at 17:23 UTC
    my $left_text = [ qw{ when rome romans} ]; my $right_text = 'When in Rome, do as the Romans.'; my $regex = join '|', map quotemeta, @$left_text; $regex = qr{\b(?:$regex)\b}i; my $found = () = $right_text =~ m/$regex/g; print $found, $/;

    The  $found = () = trick first sets the RHS in list context, and then by obtains the number of elements in the list.

    Perl 6 - links to (nearly) everything that is Perl 6.
Re: Regex Find Words
by AnomalousMonk (Archbishop) on Apr 29, 2010 at 17:22 UTC
    >perl -wMstrict -le "my $left_text = [ qw{ when rome romans} ]; my $right_text = 'When in Rome, do as the Romans.'; my $regex = qr{ @{[ join '|', @$left_text ]} }xmsi; my $found =()= $right_text =~ m/$regex/xmsg; print qq{found == $found}; " found == 3
Re: Regex Find Words
by AR (Friar) on Apr 29, 2010 at 17:23 UTC

    The Goatse operator, of course!

    my $left_text = [ qw{ when rome romans} ]; my $right_text = 'When in Rome, do as the Romans.'; my $regex = join "|", @$left_text; my $found =()= $right_text =~ m/($regex)/ig; print "$found\n";

    You're forcing the list of captures into scalar context.

    Edit: Thanks for the ++, but AnomalousMonk and moritz posted the same solution earlier than I did. I just added that it had a name.

      moritz's solution is NOT the same. Your solution and Anomalous's expect regex patterns in @$left_text, but moritz's solution takes text strings and convert them into regex patterns using quotemeta.

      Furthermore, he used \b, so his solution doesn't find "when" in "whenever" like yours does.

      Mind you, if the inputs require quotemeta, \b might not work.

      Update: Added second and third paragraph.

Re: Regex Find Words
by kennethk (Abbot) on Apr 29, 2010 at 17:27 UTC
    While the above are good answers, there is an ambiguity in the spec. What result would you expect for:

    my $left_text = [ qw{ when rome romans} ]; my $right_text = 'When in Rome, Romans do as the Romans do in Rome.';

    Would you expect a result of 3 or of 5 (or something else)? Essentially, do you want a count of all case-insensitive matches or just a count of how many search words matched? If you want the latter, the following would suit your purposes better:

    #!/usr/bin/perl use strict; use warnings; my @left_text = qw{ when rome romans}; my $right_text = 'When in Rome, Romans do as the Romans do in Rome.'; my $count = '0'; for my $search_text (@left_text) { if ($right_text =~ /\Q$search_text\E/i) { $count++ } } print "Found = $count\n"; __END__ Found = 3

    Update: And while you're at it, what do you expect for

    my $left_text = [ qw{ when rome romans} ]; my $right_text = 'When in the Terrordrome, do as the Romans.';

    If you would only expect 2 matches (ignoring that "rome" is in Terrordrome), then you will want word boundary assertions (\b):

    #!/usr/bin/perl use strict; use warnings; my @left_text = qw{ when rome romans}; my $right_text = 'When in the Terrordrome, do as the Romans.'; my $count = '0'; for my $search_text (@left_text) { if ($right_text =~ /\b\Q$search_text\E\b/i) { $count++ } } print "Found = $count\n"; __END__ Found = 2

    See perlretut or perlre for more info.

Re: Regex Find Words
by BrowserUk (Patriarch) on Apr 29, 2010 at 17:45 UTC

    Bound to miss something unspecified :)

    #! perl -slw use strict; my $left_text = [ qw{ when rome romans} ]; my $right_text = 'When in Rome, do as the Romans.'; my $regex = '(?:\b' . join( '\b|\b', map quotemeta, @$left_text ) . '\ +b)'; print $regex; my $found = () = $right_text =~ m/$regex/ig; print $found ? 'matched: ' : 'Not matched', $found; __END__ C:\test>junk42 (?:\bwhen\b|\brome\b|\bromans\b) matched: 3

    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.