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

Hello Monks,
Is it possible to store regex patterns in a scalar for later use? For instance, is there a way to get the following type of code to work?
$regex1 = (hello); $test="hello there!"; if ($test =~ /$regex1/) { print $1; }
My requirement is to include the matching if clause in a loop into which I feed a list of patterns. I have looked through a lot of regex documentation, and this is not mentioned... perhaps not surprisingly ;-)

Replies are listed 'Best First'.
Re: Storing Regex Patterns in Scalars
by Roy Johnson (Monsignor) on Mar 30, 2004 at 17:04 UTC
    If your version of Perl is sufficiently new, you can use the qr// quoting mechanism to specify a regex. Otherwise, ordinary strings can be interpolated into regexen, and what you have written above will work, if you enclose the (hello) in quotes.
    $regex1 = qr/(hello)/; # or $regex1 = '(hello)'; $test = 'hello there!'; print $1 if /$regex1/;

    The PerlMonk tr/// Advocate
Re: Storing Regex Patterns in Scalars
by duff (Parson) on Mar 30, 2004 at 17:33 UTC

    Both dragonchild and Roy Johnson say that you should be looking at qr// and while I agree, you might want to be careful about how you use it if you're also using regular expression modifiers. For instance,

    perl -le '$re = "(hello)"; $_ = "Hello world"; print $1 if /$re/i;'

    works just fine, but

    perl -le '$re = qr/(hello)/; $_ = "Hello world"; print $1 if /$re/i;'

    won't.

    You need to put the modifier with the qr// for it to be interpretted correctly. I.e.,

    perl -le '$re = qr/(hello)/i; $_ = "Hello world"; print $1 if /$re/;'

    Just a note in case it comes up :-)

Re: Storing Regex Patterns in Scalars
by dragonchild (Archbishop) on Mar 30, 2004 at 17:01 UTC
    Try the following:
    my $regex1 = '(hello)'; my $test = 'hello there'; if ($test =~ /$regex1/) { print "$1\n"; }

    It shoudl work just fine. Also, you're looking for qr//. Look for it under quoting operators.

    ------
    We are the carpenters and bricklayers of the Information Age.

    Then there are Damian modules.... *sigh* ... that's not about being less-lazy -- that's about being on some really good drugs -- you know, there is no spoon. - flyingmoose

Re: Storing Regex Patterns in Scalars
by saintmike (Vicar) on Mar 30, 2004 at 17:37 UTC
    Also, please note that there is a performance penalty if you have perl evaluate something like
    /$variable/
    every time. If you don't give perl a hint that $variable never changes, it will recompile the regex every time. To avoid that, use
    /$variable/o
    to tell "this is a variable, but it never changes, so you need to compile it only once". Here's a benchmark program to show the difference:
    use Benchmark; my $qr_regex = qr/ab{1,}c{1,}/; my $str_regex = "ab{1,}c{1,}"; my $string = "asdabdabc"; timethese(10000000, { 'string' => sub { $string =~ /$str_regex/ }, 'string/o' => sub { $string =~ /$str_regex/o }, 'qr' => sub { $string =~ /$qr_regex/ }, });
    And here are the results:
    Benchmark: timing 10000000 iterations of qr, string, string/o... qr: 11 wallclock secs (10.60 usr + 0.00 sys = 10.60 CPU) @ 943396.23/s (n=10000000) string: 11 wallclock secs (11.80 usr + 0.00 sys = 11.80 CPU) @ 847457.63/s (n=10000000) string/o: 7 wallclock secs ( 9.40 usr + 0.02 sys = 9.42 CP U) @ 1061571.13/s (n=10000000)
    -- saintmike
Re: Storing Regex Patterns in Scalars
by duff (Parson) on Mar 30, 2004 at 17:02 UTC
    Sure. Did you try it? You're missing the quotes around your string "(hello)" though.
Re: Storing Regex Patterns in Scalars
by Steve_p (Priest) on Mar 30, 2004 at 17:29 UTC

    Another way of doing this is to store a reference to your regex using qr(). For example,

    #!/usr/bin/perl -w use strict; my $re = qr/hello/; my $string1 = "hello"; my $string2 = "good bye"; if($string1 =~ $re){ print "Match $string1\n"; } if($string2 =~ $re){ print "Match $string2\n"; }
Re: Storing Regex Patterns in Scalars
by pbeckingham (Parson) on Mar 30, 2004 at 17:34 UTC
    my $regex1 = qr{(hello)}; print $1 if 'hello there!' =~ $regex1;