gary.monson has asked for the wisdom of the Perl Monks concerning the following question:

In a test script, I am trying to match a line using like(), which requires the qr// form of regex. However, the /m modifier does not seem to work. A sample script illustrating the problem follows:

!/usr/bin/env perl use strict; use warnings; use Test::More qw(no_plan); my $string = "abc\ndef\nghi"; # (1) Passes like($string, qr/def/m, 'found def'); # (2) Passes like($string, qr/^def/m, 'found ^def'); # (3) Fails like($string, qr/def$/m, 'found def$'); # (4) Fails - this is the test I want to run like($string, qr/^def$/m, 'found ^def$'); # (5) Passes ok(($string =~ m/^def$/m), 'found ^def$'); # (6) Passes - supposedly the equivalent of (4)? ok(($string =~ m/(?m-xis:^def$)/), 'found ^def$');

In this toy example, I am looking for a line matching (exactly) 'def' within the string. It may be the first line, the last line (without a newline), or anywhere in between. In this example, it is in the middle.

My ideal match would be qr/^def$/m (test 4), but it does not seem to work. The fact that (2) passes, and (3) fails leads me to believe that it is just the '$' that has the problem.

I would much appreciate if anyone could enlighten me as to what I am doing wrong.


Replies are listed 'Best First'.
Re: Use of qr// modifier with Test::More::like
by ysth (Canon) on Mar 27, 2008 at 03:14 UTC

      Thanks!! The alternative version works perfectly.

      Unfortunately, I don't like my chances of getting our servers upgraded to 5.8.9. We are still trying to get production off 5.6!!


Re: Use of qr// modifier with Test::More::like
by kyle (Abbot) on Mar 27, 2008 at 02:17 UTC

    I'm not sure this has anything to do with Test::More.

    use Test::More 'tests' => 7; # all tests pass my $string = "abc\ndef\nghi"; my $pattern = qr/def/; my $pattern_m = qr/^def$/m; ok( $string =~ /^def$/m, 'literal/m pattern matches' ); ok( $string =~ $pattern, 'plain qr stored pattern matches' ); is( "$pattern_m", '(?m-xis:^def$)', 'qr/m as string: (?m-xis:^def$)'); like( $string, '/(?m-xis:^def$)/', 'string (?m-xis:^def$) matches' ); ok( $string =~ /(?m-xis:^def$)/, 'literal (?m-xis:^def$) matches'); ok( ! ($string =~ $pattern_m), 'qr/m stored pattern does not match' ); unlike( $string, $pattern_m, 'qr/m stored pattern not "like"' );

    Perhaps I've done something foolish here (using Test::More to check Test::More, maybe), but this looks like a bug.

    Update after gary.monson's reply: Sorry I wasn't clear. This looks to me like a bug in perl. Without running it, I would have expected the last two tests to come out the opposite of how they did. I originally thought the OP's behavior might have to do with how Test::Builder uses string eval to do its comparison, but that doesn't seem to be the case.

      Sorry - I probably didn't make my worries as clear as they should be. I am wondering if it is a problem with qr//m itself, rather than Test::More. Otherwise, maybe Test::More is doing something with the qr//m that I wasn't expecting? I tried looking inside the source of Test::More, but got lost pretty quick.

      When you say "this looks like a bug" - do you mean in Test::More, perl, or my code?

      If your code is supposed to show that Test::More is fine, well, I'm not sure that it does. Your last test *should* be failing rather than passing, for the same reason my test # 4 should be passing. $string *should* match $pattern_m, so like() should pass, and unlike() should fail.