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

Hi Monks, I *think* I would like to save a regex in a file then evaluate it in my program:
$string = "alphabet is abc...\n"; $re = ReadREFromFile(); $re = 'm/abc/'; #for testing... print "match\n" if ($string =~ $re);
It seems "cleaner" to put the delimiters (and I *like* seeing the "m"...). Plus I might not want to use the default delimiters in the config file...
The above example doesn't work, any suggestions? THANKS !!!

Replies are listed 'Best First'.
Re: save regex in a file?
by japhy (Canon) on Oct 16, 2001 at 09:11 UTC
    Use qr//:
    $re = qr/abc(def|ghi)(?:jkl)+/i; open RE, "> my_re.pl" or die "can't write to my_re.pl: $!"; print RE $re; close RE; # later open RE, "< my_re.pl" or die "can't read my_re.pl: $!"; chomp($re = <RE>); close RE;

    _____________________________________________________
    Jeff[japhy]Pinyan: Perl, regex, and perl hacker.
    s++=END;++y(;-P)}y js++=;shajsj<++y(p-q)}?print:??;

      A slightly different approach using the same idea is to put the qr// statements directly in the file and eval them after reading in. This improves the readability if the file is to be edited by human beings.

      So the regex data file would look like this:

      qr/abc/i qr/^\d+$/m ...
      Reading in and evaling (of course this might introduce some security problems) could then be done this way:
      my @regexes; # read in open RE, "< my_re.pl" or die "can't read my_re.pl: $!"; while(<RE>) { chomp; push @regexes, eval; } close RE; # and do the matching for my $re (@regexes) { if ($text =~ $re) { # do something } }

      With some extra effort one could even allow multiline regexes in the data file.

      -- Hofmator

Re: save regex in a file?
by chipmunk (Parson) on Oct 16, 2001 at 08:31 UTC
    If you really want to put the m and the delimiter in the file, you will have to remove them before applying the regex. Something like this:
    $re =~ s/^m//; $re =~ s/^.//; $re =~ s/.$/; $string =~ $re;
    Note that this may not give the same behavior as a normal match if you've used a delimiter that also appears in the regex, e.g. m|foo\|bar|
      It is a bummer to hear that. It really seems like a big disadvantage to not be able to specify the delimiter in the file as I know there are "special" delimiters that are sometimes used. It also means that I have to separately ask if there are any operators "ie: case insensitive" as an example...m/abc/i

      Would eval() help? I tried the simple case I could think of and it didn't seem to work...

      Thanks for ideas!!!
        Using eval would just introduces a whole new bag of worms; I don't think it would be the best solution. Fortunately, you can specify the modifiers within the regex. Here are two quick examples.
        (?i)abc (?s-m:^start.*end)
        The first turns on case-insensitivity for the entire pattern. The seconds turn on single-line matching and turns off multi-line matching for the part of the pattern within the parentheses.

        perlre explains this syntax in more detail.

Re: save regex in a file?
by Zaxo (Archbishop) on Oct 16, 2001 at 09:35 UTC

    There are a number of builtin ways to do this, partucularly if the regex is stored in perl syntax.

    1. do FILE;
    2. open FL, $fname; $re = <FL>; close FL;
    3. require FILE
    4. use MODULE
    Each listed way has it's own conventions for getting a value out. The elegant way if to make the file a module:
    package VIR; our $vir = qr/My\s+[Rr]egex/; 1;
    Usage:
    #!/usr/bin/perl -w use strict; use lib '/location/of/lib/'; use VIR; $_="My regexen"; print "found\n" if m/$VIR::vir/;
    Each listed way has it's own conventions for getting a value out.

    After Compline,
    Zaxo

Re: save regex in a file?
by Mosley (Novice) on Oct 16, 2001 at 09:53 UTC
    I have this working, it does not hide delimiters but it does allow you to pick which regex you want to use. Just save them in $regexFile. Mosley
    $regexNum = 0; $regexFile = "regex.txt"; $string = "alphabet is abc...\n"; print "Content-type: text/html\n\n"; if ($regexNum gt 0) { open FILE, $regexFile or die "Cannot open $regexFile file for read + :$!"; do { $re = <FILE> } until $. == $regexNum || eof; close(FILE); chomp($re); if ($string =~ m/$re/) { print "Matched this pattern - $re."; } else { print "This pattern - $re - not matched."; } } else { print "Regex not selected"; }