http://www.perlmonks.org?node_id=870806

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

Monks,

I'd like to read a bunch of regular expressions from a flat text for use in a script. After I read the file, how do I tell Perl thats this 'data' is a regular expression?

I'd like to accomplish something like the following.

#!/usr/bin/perl use strict; use warnings; my $data = "duck"; while(<DATA>) { if ($data =~ $_) { print "$data\n"; } } __DATA__ s/duck/luck/qr

Replies are listed 'Best First'.
Re: Store regular expressions in a file.
by BrowserUk (Patriarch) on Nov 11, 2010 at 10:46 UTC

    You could eval the code into existence. People decry it, but it is one thing that makes dynamic languages so powerful:

    #!/usr/bin/perl use strict; use warnings; my $data = "duck"; while(<DATA>) { chomp; my $code = eval "sub{ \$_[0] =~ $_ }" // die $@; if( $code->( $data ) ) { print "$data\n"; } } __DATA__ s/duck/luck/

    Produces:

    c:\test>junk02 luck

    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
Re: Store regular expressions in a file.
by cdarke (Prior) on Nov 11, 2010 at 10:58 UTC
    this 'data' is a regular expression

    No, it is not a regular expression, only the duck is a regular expression. s is a Perl operator. If you can it would be a lot easier to have two columns, the first being the RE pattern ('duck') and the second being the replacement text ('luck') and then read them into variables (using split) - it is perfectly valid (and common) to store an RE in a Perl variable.

    Otherwise you will be reduced to doing nasty things like eval, and you don't want to go there.
      So something like this? I don't get any output.

      Thanks

      #!/usr/bin/perl use strict; use warnings; my $data = "duck"; my $r; while(<DATA>) { chomp; my ($x, $y) = split(/\s/, $_); $r->{$x} = qr/$y/; if ($data =~ $r->{"duck"}) { print "$data\n"; } } __DATA__ duck s/duck/luck/
Re: Store regular expressions in a file.
by roboticus (Chancellor) on Nov 11, 2010 at 12:56 UTC

    yoda54:

    I put this together:

    #!/usr/bin/perl use strict; use warnings; # Read the regexes my @Rexes; while (my $t=<DATA>) { chomp $t; last if $t=~/^$/; my ($regex, $repl) = split /\t+/, $t; push @Rexes, [ qr($regex), $repl ]; } # Process the text while (my $l = <DATA>) { $l=~s/$$_[0]/$$_[1]/eg for @Rexes; print $l; } __DATA__ duck cluck a(b+)c c$1a That bird says "duck!" xyzzy plugh ac abc abbc abbbc

    It mostly works, but as you can see from the following run, I haven't been able to make back references work...

    roboticus@Boink:~ $ perl pm870806_dyn_regex.pl That bird says "cluck!" xyzzy plugh ac c$1a c$1a c$1a

    ...roboticus

      #!/usr/local/bin/perl use strict; use warnings; use String::Interpolate qw(safe_interpolate); # Read the regexes my @Rexes; while (my $t = <DATA>) { chomp $t; last if $t =~ /^$/; my ($regex, $repl) = split /\t+/, $t; push @Rexes, [ qr($regex), $repl ]; } # Process the text while (my $l = <DATA>) { $l=~ s/$$_[0]/safe_interpolate($$_[1])/eg for @Rexes; print $l, "\n"; } __DATA__ duck cluck a(b+)c \uc${1}\ua That bird says "duck!" xyzzy plugh ac abc abbc abbbc
      That bird says "cluck!" xyzzy plugh ac CbA CbbA CbbbA

        ++eff_i_g:

        Sweet! I played with it for a while before giving up on the capture groups. I'll have to be sure to keep this handy!

        ...roboticus

        Thanks everyone for the enlightenment!!
Re: Store regular expressions in a file.
by mjscott2702 (Pilgrim) on Nov 11, 2010 at 11:42 UTC
    If you just wanted to create regular expressions for matching from a file, you could use the qr quoting operator, but don't think that will work for substituting as you appear to want to do - as others have pointed out, you would probably have to use eval for that.
      I see.

      Thanks

        This also works:

        #!/usr/bin/perl use strict; use warnings; my $data = "duck"; while(<DATA>) { chomp; my( $find, $replace ) = split ' ', $_, 2; if( $data =~ s[\Q$find][$replace]e ) { print "$data\n"; } } __DATA__ duck luck

        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.
Re: Store regular expressions in a file.
by sundialsvc4 (Abbot) on Nov 11, 2010 at 12:08 UTC

    The magic voodoo you are looking for is:   qr/some_expression/.

    This operator compiles a regular expression that is made from some_string.

    When constructing the string, be careful:   you might be tempted to use interpolation (double-quotes...) but this will cause the “rabbit-food” of the regex syntax itself to be turned into escape-characters.

    Furthermore, you might find that you can successfully put a string-variable reference into the regular expression string (i.e. without using qr//), and find that it is properly interpolated.   If you simply want to substitute “a particular string to search for” into an otherwise-fixed expression, this is one way to do that.

    If the regexes to be used are truly arbitrary, however, you will want to use qr//, and to enclose that statement in an eval block to trap runtime errors caused by invalid regex syntax.

Re: Store regular expressions in a file.
by JavaFan (Canon) on Nov 11, 2010 at 10:48 UTC
    I'd like to read a bunch of regular expressions from a flat text for use in a script. After I read the file, how do I tell Perl thats this 'data' is a regular expression?
    Replace "regular expression" with "number", and ask yourself the same question. How does Perl do that?