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

I found this code in a module I'm reviewing and thought I'd found a bug:

   if ($type =~ "text/plain") { ...

I thought it wouldn't work to have a string on the right-hand side of =~ operator, but as far as I can tell it does. I thought it would have to be done like this to delimit a regex with ":

   if ($type =~ m"text/plain") { ...

Is this a recent change in Perl (this is 5.8.5) or did I just miss this in my regex education?

-sam

Replies are listed 'Best First'.
Re: Naked quotes work like m//?
by BrowserUk (Patriarch) on Dec 03, 2004 at 21:44 UTC

    A quoted string or a scalar has successfully bound via =~ as long as I've been doing Perl, since 5.6.1:

    [21:40:24.90] P:\test>perl5.6.1 -wle" 'fred' =~ '(re)' and print $1" re [21:41:41.51] P:\test>perl5.6.1 -wle"$re = '(re)'; 'fred' =~ $re and p +rint $1" re

    But if you need modifiers, then you need m//opts


    Examine what is said, not who speaks.
    "But you should never overestimate the ingenuity of the sceptics to come up with a counter-argument." -Myles Allen
    "Think for yourself!" - Abigail        "Time is a poor substitute for thought"--theorbtwo         "Efficiency is intelligent laziness." -David Dunham
    "Memory, processor, disk in that order on the hardware side. Algorithm, algorithm, algorithm on the code side." - tachyon

      But if you need modifiers, then you need m//opts

      For the "xism" modifiers (as I like to call them) you can use the (?imsx-imsx) and (?imsx-imsx:) assertions. See perlref for more on that.

      ihb

      See perltoc if you don't know which perldoc to read!
      Read argumentation in its context!

        Yes, I was thinking about the /gc modifiers. I've often wished that there were some way to embed these into a qr// prepared regex.

        If we had a reentrant regex engine, that concept might actually be meaningful:)


        Examine what is said, not who speaks.
        "But you should never overestimate the ingenuity of the sceptics to come up with a counter-argument." -Myles Allen
        "Think for yourself!" - Abigail        "Time is a poor substitute for thought"--theorbtwo         "Efficiency is intelligent laziness." -David Dunham
        "Memory, processor, disk in that order on the hardware side. Algorithm, algorithm, algorithm on the code side." - tachyon
Re: Naked quotes work like m//?
by bart (Canon) on Dec 03, 2004 at 23:33 UTC
    Perl has been able to use plain strings as regexes for as long as I know. Usually that is intended to be used as
    $pat = 'fo.d'; $s =~ $pat
    but what you got here is just a weird case of pretty much the same, and as such, works too, for some meaning of "work".

    Do note that using // or "" as delimiters is not the same thing. One's a regex, the other a string. Oh, and using m with quotes as delimiter, makes it a regex again. Witness the difference:

    #! perl -w $\ = "\n"; # one line per print $s = "abc\\.def"; print $s; $s =~ /(\\.)/ and print $1; $s =~ "(\\.)" and print $1; $s =~ m"(\\.)" and print $1;
    resulting in:
    abc\.def
    \.
    .
    \.
    
      A bit confused here. The string "(\\.)" isn't the same as the regexen in the other two examples. Because stringification removes a level of backslashes, so the regex applied in the second example is really (\.) which is, of course, very different from (\\.)

      I think the backslash obscures the issue a lot, though, so I added another test without any backslashes: $s =~ "(a.c)" and print $1;

      It produced abc which seems to me to indicate that the string is actually being evaluated as a regex. And I think you're saying that this isn't the case.

      So what am I missing? Or misinterpreting?

        What you're missing is that the value of the string is interpreted as the regex, and not how you write the source code for the string. So a double backslash in the source code is actually just a single backslash in the string, and in the regex; and 4 backslashes in the source code is actually a double backslash in both string and regex.
Re: Naked quotes work like m//?
by friedo (Prior) on Dec 03, 2004 at 21:52 UTC
    It looks like it behaves like a regex delimiter without the m.

    perl -MO=Deparse -e '$a = "foo"; print 1 if $a =~ "foo"' $a = 'foo'; print 1 if $a =~ /foo/;
    It will match a pattern, too, not just a literal string. print 1 if $a =~ "fo."; works fine.

    Neat.

Re: Naked quotes work like m//?
by tachyon (Chancellor) on Dec 03, 2004 at 23:25 UTC

    I too have noted that 'bug' as well which as you note turns out not to be one. It is possibly a documentation bug. Probably like me you remembered reading If ``/'' is the delimiter then the initial m is optional in perlre and then made the assumption (IMHO justified) that this implicitly indicates that:

    If ``/'' is NOT the delimiter then the initial m is NOT optional.

    This of course is an implicit assumption. perlre does not define the behaviour when the delimiter is not a / and the m is missing. As you note the m is optional with a (small) range of other delimiters. This dates back to Perl 5.6.0 and perhaps earlier.

    There are actually only a limited number of delimiters that will work in this /* m free, non /* context. Essentially any perl expression that will evaluate as a stringy thing and is a valid RVALUE can be used:

    $a = "2foobar\n"; print $a if $a =~ m"foo"; print $a if $a =~ eval{"bar"}; print $a if $a =~ q!foo!; print $a if $a =~ (6*7-40); # yes this evaluates to 2, gets stringif +ied and matches

    Practically speaking that means " and ' with most of the other commonly used non / regex delims like ! , | {} all creating syntax errors or not matching.

    cheers

    tachyon

      I'm so confused as to what you're going on about here. The code cited in the original post has absolutely nothing to do with "alternate delimiters for m//" and the various other things you're going on about.

      All that is happening is that =~ will use ANY SCALAR on the right hand side as a regex. It stringifies it and treats that value as a regex, then applies it to the left hand as normal.

      So in short, anything that produces a scalar can be used on the right hand side of the =~ operator, including, for example:
      $a =~ { foo }; $b =~ [ "bar" ];
      And so forth. The "m" isn't optional for these because they aren't regexes! They're simply scalar producers.