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

Monks ~

I wanted to write a test to see if a given scalar contains a quoted regular expression. I don't care if the regex is valid or what it matches as long as perl thinks it's a real quoted regex. I discovered that it's either much easier than I thought, or I'm missing something. Or both :)

#!/usr/bin/perl use strict; use warnings; my %qrs = ( string1 => 'foo', string2 => '(xism)', regex => qr/foo/, 'regex?' => '(?-xism:foo)', ); while( my( $key, $regex ) = each %qrs ) { print "'$key' "; print $regex =~ /\(\?\-xism:/ ? 'YES: ' : 'no: '; print $regex; print ' (and matches)' if 'foo' =~/$regex/; print "\n"; }

And here's the output:

'regex?' YES: (?-xism:foo) (and matches)
'regex' YES: (?-xism:foo) (and matches)
'string1' no: foo (and matches)
'string2' no: (xism)

It looks like creating a scalar of the pattern "(?-xism:$STUFF)" is enough to make perl believe it's a quoted regex. I've tried to find a definitive in perldoc, man pages, The Camel, etc. answer and haven't.

Is it really this cool and simple?


--
man with no legs, inc.

Replies are listed 'Best First'.
Re: Walks like a regex, quacks like a regex...
by kvale (Monsignor) on Sep 23, 2003 at 03:24 UTC
    Well, both  foo and (?-xism:$STUFF) are regular expressions and valid strings. A better way to distinguish the two is to look at the reference:
    $reg = qr'foo'; $str = 'foo'; $str2 = '(?-xism:foo)'; $reg_ref = \$reg; $str_ref = \$str; $str2_ref = \$str2; print "$reg -> $reg_ref\n"; print "$str -> $str_ref\n"; print "$str2 -> $str2_ref\n";
    yields
    (?-xism:foo) -> REF(0x80635ac) foo -> SCALAR(0x80635dc) (?-xism:foo) -> SCALAR(0x8063600)

    -Mark

      Nice test -- thanks.
      --
      man with no legs, inc.
Re: Walks like a regex, quacks like a regex...
by BrowserUk (Patriarch) on Sep 23, 2003 at 03:28 UTC

    Basically, any string can be used as a regex. Vis.

    print 'Matched!' if 'fred' =~ 'fred' Matched!

    Or perhaps more bizarrly,

    print 'Matched!' if ' ' =~ pack 'V', 538976288 Matched!

    Whether an arbitrary string will survive compilation and do anything useful, or what it will do if it does is a harder question to answer.

    Question: Would a legless duck be a free floating spirit? :)


    Examine what is said, not who speaks.
    "Efficiency is intelligent laziness." -David Dunham
    "When I'm working on a problem, I never think about beauty. I think only how to solve the problem. But when I have finished, if the solution is not beautiful, I know it is wrong." -Richard Buckminster Fuller
    If I understand your problem, I can solve it! Of course, the same can be said for you.

Re: Walks like a regex, quacks like a regex...
by Abigail-II (Bishop) on Sep 23, 2003 at 08:04 UTC
    Perl doesn't do "hmmm, it walks like a regex, it quacks like a regex, so this thing must be a regex". No, Perl is more like "hey, you use this thing as if it's a regex, so it'll be a regex". Strings, numbers, arrays, hashes, anything can be a regex:
    $ perl -wle 'print "Yes" if 8 =~ @INC' Yes $

    It's all in the same line as strings becoming numbers and vica versa, arrays becoming numbers in scalar context, etc. This could lead to bizarre looking code like:

    $ perl -le 'print "Yes" if %INC =~ %INC' Yes $

    Abigail

Re: Walks like a regex, quacks like a regex...
by belg4mit (Prior) on Sep 23, 2003 at 03:25 UTC
    Umm technically all of your values are "regexen".
    /foo/;
    is perfectly legal. So is
    qr/foo/;
    or for that matter
    /qr\/foo\//;
    What you seem to be after is regex meta-characters... see perlre

    --
    I'm not belgian but I play one on TV.

Re: Walks like a regex, quacks like a regex...
by Roger (Parson) on Sep 23, 2003 at 03:37 UTC
    You should also checkout the CPAN module YAPE::Regex, which does regular expression parsing in perl.
Re: Walks like a regex, quacks like a regex...
by shenme (Priest) on Sep 23, 2003 at 04:58 UTC
    Wait, are you asking how to tell if a value is the result of qr{^[Zz]owie!?$}.   Please don't hit me - aren't you looking for this?
    if( ref $regex eq 'Regexp' ) { print "That's an affirmative, base.\n"; }
      Hang on, but that only works in the case:
      regex1 => qr/foo/
      But not in the case:
      regex2 => '(?-xism:foo)'
      Where regex1 is compiled as a Regexp, and regex2 is compiled as a string. The reference to regex1 yields a Regexp, the reference to regex2 yeilds nothing, so it will not match regex2 which is a valid regular expression.
        Well that was (is) my confusion at his mentioning the phrase "a real quoted regex".   _If_ he means a compiled qr() regex then while he's still throwing the result reference value around the ref() is the right way to check.

        But once he forces the qr() reference value to be stringified, it'll end up in the "(?-xism:^[Zz]owie!?$)" form and he'll have to recognize that 'unique' format.

        And then his checking will fail because the leading part shows which options are and are not in effect.   Using qr{^Zzowie!?$}sm will, when stringified, result in "(?ms-xi:^[Zz]owie!?$)".   Zowie!

Re: Walks like a regex, quacks like a regex...
by legLess (Hermit) on Sep 23, 2003 at 04:17 UTC
    So, replying to my own question, I just figured out my disconnect here: cloistering. I'd not used it before, so the "?-xism" didn't look familiar to me. It makes even more sense than I thought. Thanks for the replies.
    --
    man with no legs, inc.