in reply to Applying a RegEx in a variable

I can't think of a really elegant way to do it, that is without (A) requoting your $RegEx or (B) ripping it to bits to get at what's inside it. The only one-liner I thought of that comes anywhere close is:
$String =~ /(??{substr($RegEx,1,-2)})/;
But that has the defects that you have to know you'll only ever have one modifier in $RegEx, and that it doesn't do case-insensitive matching. What we need to be able to do is use variables as regex modifiers - but I don't think we can. Or can we?

It's probably simpler to do the requoting suggested above, but if you can't do that for some reason, and you need the flexibility, I propose brute force:
($x,$s,$m) = split(/\//,$RegEx); sub p {print "Match: ",$&||"none"," Pre: ",$`||"none"," Post: ",$'||"n +one","\n"} if ($m eq 'i') {$String =~ /$s/i;p} if ($m eq 'm') {$String =~ /$s/m;p} if ($m eq 's') {$String =~ /$s/s;p} if ($m eq 'x') {$String =~ /$s/x;p} if ($m eq 'o') {$String =~ /$s/o;p} if ($m eq 'im') {$String =~ /$s/im;p} if ($m eq 'is') {$String =~ /$s/is;p} if ($m eq 'ix') {$String =~ /$s/ix;p} if ($m eq 'io') {$String =~ /$s/io;p} if ($m eq 'mis') {$String =~ /$s/mips;p} if ($m eq 'mix') {$String =~ /$s/mix;p} if ($m eq 'mio') {$String =~ /$s/mio;p} if ($m eq 'smix') {$String =~ /$s/smix;p} if ($m eq 'smio') {$String =~ /$s/smio;p} if ($m eq 'xsmio') {$String =~ /$s/xsmio;p}
Of course, this doesn't allow for global and continuous global matching, but that way madness lies...

§ George Sherston

Replies are listed 'Best First'.
Re: Re: Applying a RegEx in a variable
by Hofmator (Curate) on Aug 10, 2001 at 15:58 UTC

    Well, your way of taking it aparts breaks much too easy, e.g. on

    m#bla# /bla\// /bla/g # as you already mentioned ...
    But why shouldn't you use eval (what you call 'requoting', a rather strange expression imho), that's what it is made for. Don't reinvent the wheel.

    In the end, you are trying to parse Perl and as the saying goes only perl can parse Perl (or was it PERL can parse perl? :).

    Being extremley cautious about the content of anything you eval, however, is a totally different issue ...

    -- Hofmator

      Hm. Yes. Quite right.
      @a = split(/\//,$RegEx); $m = pop @a; shift @a; $s = join("/",@a);
      Better?
      On the other question, I don't think eval does it, because it doesn't return the dynamically scoped variables. What I meant by 'requoting' was the kind of thing abstracts suggested above (which is a fine solution if the problem allows it to work, but seemingly it doesn't). So I think there's no alternative to thuggery.

      One of the one-hand-clapping paradoces of perl, as I understand it, is that it encourages us to do what we like with it, including the things it doesn't let us do. Perl lets you parse anything, even perl (or PERL)! Only perl allows something that isn't perl to parse perl! La lutte continue!

      § George Sherston

        <some code>
        Better?
        Yes, it's better but it still breaks. Consider e.g. giving the modifiers in a different order (/mi instead of your /im), giving multiple modifiers (/ii is perfectly legal) using different delimiters (m!pattern!) and so on.

        I'm not saying that it is impossible to parse this regex construct by hand - but why should want to do that? The eval solution always works - if $RegEx is a legal perl pattern matching operator and you can pass out anything with the construct I explained elsewhere in this thread.

        Your solution restricts the number of possible patterns and the ways of providing them. The qr solution suffers from the same problems, only it is less restrictive. And the eval is slow but gives you the whole range of possible pattern matching constructs (even s/// would work) and more (which can become a problem/security concern).

        To sum up, without knowing the problem better (where does the $RegEx come from, what should be achieved with it, ...) we cannot tell which solution to favour. And as always, TMTOWTDI :)

        -- Hofmator

      let`s keep dangerous content of the eval out of this...

      I want to eval the expression whilst retaining information on the special
      RegEx vars ($1..n, $&,$`,$', etc, etc) It really SHOULD be possible

      I`m actually very close to printing the regex to a file, run the file as a Perl
      program, let it print the vars to another file, and read them back into the
      parent.... Now that`s what I call desperation....

      GreetZ!,
        ChOas

      print "profeth still\n" if /bird|devil/;

        Well, you can always do it the qr// way (this is better anyway if you are using the same regex more than once). Or you can do it along these lines:

        my $match; eval "\$String =~ $RegEx"; \$match = \$&"; print $match;
        The code executed within the eval has access to the variables outside - again it works the same way as if the evaluated code was in a code block of its own.

        -- Hofmator