http://www.perlmonks.org?node_id=880672

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

I recently had the opportunity to use brian d foy's post about how to use smart matching to test against many regexes. This is for a web crawler to check my work site for bad links (and to gather links for accessibility testing).

The smart matching doesn't seem to be working. Here is my test code:

use 5.010; my $string = q(foo); my @patterns = map { qr/$_/i } qw( foo ba(r|z) quux ); say @patterns; if( $string ~~ @patterns ) { say q(matched); }

...and this is the output:

gizmo@veterok: <bash>[~/dev/smart_match_regex_test] $ ./test.pl (?i-xsm:foo)(?i-xsm:ba(r|z))(?i-xsm:quux)

I am rather befuddled why this isn't working and what I might be doing wrong.

Thanks,
gizmo

Replies are listed 'Best First'.
Re: string/array smart match regex failing me
by toolic (Bishop) on Jan 05, 2011 at 20:54 UTC
    I get a different output:
    (?i-xsm:foo)(?i-xsm:ba(r|z))(?i-xsm:quux) matched
    What version of perl are you using?
    $ perl -v This is perl 5, version 12, subversion 2 (v5.12.2) built for x86_64-li +nux

    See also Smart match changes, for example.

      Same here, it worked on both of: 5.12.2 on fedora 14 and 5.10.1 on another linux

      use strict; use warnings; use 5.010; my $string = q(quux); my @patterns = map { qr/$_/i } qw( foo ba(r|z) quux ); say @patterns; if( $string ~~ @patterns ) { #say q(matched); say qq(This matched: $&); }

      I'm using 5.10.0

      I didn't get around to testing it against something a bit more current but this is a work machine.

      Running on my machine at home (5.10.1) it matched.

      We do have 5.12.1 installed on a test machine and it worked as expected. I guess I need to pass along the request to put 5.12.1 into production.

      Thanks for the help everyone.

Re: string/array smart match regex failing me
by ikegami (Patriarch) on Jan 05, 2011 at 22:50 UTC

    Smart matching was introduced in 5.10.0, and many problems were found after release. Don't be surprised if you run into some of them when using 5.10.0. 5.10.1 (and thus 5.12.x) fixes many problems with smart-matching.

    $s ~~ @pats

    can be written as

    grep $s =~ $_, @pats

    (Although I suspect the latter is a bit less efficient.)

Re: string/array smart match regex failing me
by JavaFan (Canon) on Jan 05, 2011 at 21:01 UTC
    Considering none of the strings in @pattern equals $string, I'm not surprised.

    You cannot use ~~ to match a given string with an array of patterns. You can do the opposite: match a pattern against an array of strings.

    But you're matching a string against an array. And that is true iff there's an exact match of the string with at least one element of the array.

    See the perlsyn manual page.

      You cannot use ~~ to match a given string with an array of patterns.

      Yes you can. From perlsyn of 5.10.1, 5.12.0 and 5.12.2, the first matching case is

      Any ~~ Array match against an array element grep $a ~~ $_, @$b

      which repeatedly does

      Any ~~ Regex pattern match $a =~ /$b/

      Example:

      use feature qw( say ); my @pats = map qr/$_/, qw( a c ); for (qw( aaa bbb ccc ddd )) { say if $_ ~~ @pats; }
      aaa ccc

      I didn't check the 5.10.0 docs since smart matching underwent major fixes in 5.10.1.

      You cannot use ~~ to match a given string with an array of patterns

      except that toolic's reply demonstrates that it does work and the perlsyn docs include a table in the 'Smart matching in detail' section that includes:

      $a $b Type of Match Implied Matching Code ====== ===== ===================== ============= ... Any Array match against an array element[3] grep $a ~~ $_, @$b ...

      which clearly shows that an element by element smart match is performed, so an array of Regexs should work as the OP expects (and as toolic confirms). My best guess is that the OP is using 10.0 which introduced the smart match operator and a pile of bugs. 10.1 and later fixes a pile of smart match related bugs.

      The brian d foy post linked by the OP is rather more explicit that the technique works than the Perl docs and, given the author, is fairly likely to be reliable.

      True laziness is hard work
Re: string/array smart match regex failing me
by oko1 (Deacon) on Jan 05, 2011 at 21:14 UTC

    JavaFan nailed it, but here's a way to do what you want:

    #!/usr/bin/perl -w use strict; use 5.010; my $string = q(foo); map { say "$_: ", $string =~ /$_/i?"Matched":"No match" } qw( foo ba(r +|z) quux );

    Update: Added the 'Matched/No match' bits.

    -- 
    Education is not the filling of a pail, but the lighting of a fire.
     -- W. B. Yeats