http://qs321.pair.com?node_id=103786

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

Fellow Celebates,

This should be simple, and I`m sure it CAN be done...Sad enough I`m also
sure that I haven`t been able to do it yet......

I want to apply a RegEx to a variable .. easy... BUT the RegEx resides
in a scalar...
Vars:
my $String="1234A4321"; my $RegEx="/a/i";
Code1:
{ $String=~/a/i; print "Match: ",$&||"none"," Pre: ",$`||"none"," Post: ",$'||"none","\ +n"; }
prints: Match: A Pre: 1234 Post: 4321
Good.. I had expected that...

Code2..n:
{ $String=~$RegEx; print "Match: ",$&||"none"," Pre: ",$`||"none"," Post: ",$'||"none","\ +n"; } { eval $String=~$RegEx; print "Match: ",$&||"none"," Pre: ",$`||"none"," Post: ",$'||"none"," +\n"; } { eval { $String=~$RegEx; }; print "Match: ",$&||"none"," Pre: ",$`||"none"," Post: ",$'||"none"," +\n"; }
prints:
Match: none Pre: none Post: none
Match: none Pre: none Post: none
Match: none Pre: none Post: none
Match: none Pre: none Post: none

This is frustrating.. I`m just looking for code X (be it in an eval, or not, I don`t care)
that prints Match: A Pre: 1234 Post: 4321, given $String and $RegEx....

Any help would be very much appreciated...

GreetZ!,

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

Replies are listed 'Best First'.
Re: Applying a RegEx in a variable
by abstracts (Hermit) on Aug 10, 2001 at 13:51 UTC
    Hello

    Try reading in perlop about the qr operator. Here is an example about how it can be used:

    my $String="1234A4321"; my $RegEx=qr/a/i; $String =~ $RegEx; print "Match: ",$&||"none"," Pre: ",$`||"none"," Post: ",$'||"none","\ +n"; # Match: A Pre: 1234 Post: 4321
    Hope this helps,,,

    Aziz,,,

    Update: Yes, you got the right idea there using

    $re = eval "qr$regexp_val";
    Make sure you trust the source of your regexp before feeding it to eval.
      Hmmmmmm.....Actually....no ;))

      I have no influence over the regex, it could come
      from a file, or from user input... it`s really a
      scalar...

      BUT!..... I can do
      my $Tmp="/a/i"; my $RegEx=eval "qr$Tmp";
      For wich I can build a working construct... hmmmm...
      I`m going to explore this a bit more....
      So actually it DID help!! .....Thanks! ;)))

      ... A little bit later ...

      Hmmmmm.... maybe it didn`t help... I`ll try some more ;))

      ... A little bit more later ...

      Okay.. I got it to work!! cheer!!... I`ll post the code where
      it`s going to be in hopefully next week.... thanks!!

      GreetZ!,
        ChOas

      print "profeth still\n" if /bird|devil/;
Re: Applying a RegEx in a variable
by Hofmator (Curate) on Aug 10, 2001 at 14:53 UTC

    You could also eval it directly - depends on your application

    # eval returns the value of the last evaluated expression if (eval "\$String =~ $RegEx") { print "Matched"; } else { print "Not matched"; }
    However this doesn't provide you with access to the regex variables (like $&, $1, $', ...) as they are dynamically scoped - imagine the eval being a separate block of code.

    From your post I'm not sure if you are aware of the difference between eval BLOCK and eval EXPR so I'd suggest reading up on that ...

    -- Hofmator

Re: Applying a RegEx in a variable
by George_Sherston (Vicar) on Aug 10, 2001 at 15:37 UTC
    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

      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
        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/;