CGI/Perl Guide | Learning Center | Forums | Advertise | Login
Site Search: in

  Main Index MAIN
INDEX
Search Posts SEARCH
POSTS
Who's Online WHO'S
ONLINE
Log in LOG
IN

Home: Perl Programming Help: Intermediate:
using eval with regex's

 



clinton
Novice

Nov 10, 2003, 3:54 PM

Post #1 of 4 (484 views)
using eval with regex's Can't Post

Hi,

I am trying to use eval () to evaluate a regex that incorporates user-specified options (//i, //s, etc.) My code looks like this:

74 my $compare = <<COMPARE;
75 if ("$_" =~ /.*\Q$ARGV[1]\E.*/$ARGV[3]) {
76 "$_" =~ s/$ARGV[1]/$ARGV[2]/$ARGV[3];
77 }
78 else
79 {}
80 COMPARE
81
82 eval($compare);
83 print $@;

$_ is a file containing the word "document" (newlines have been chomped).
$ARGV[1] = document
$ARGV[2] = boo
$ARGV[3] = si

the error message printed out is "Can't modify constant item in substitution
(s///) at (eval 1) line 2, at EOF"

The double-quotes around $_ is necessary (you get a "use strict"-ish error if
you omit them).

Any ideas?


KevinR
Veteran


Nov 10, 2003, 7:36 PM

Post #2 of 4 (481 views)
Re: [clinton] using eval with regex's [In reply to] Can't Post

Are you sure the error message is associated with the code you posted and not some prior part of the script? I don't think you can use scalars in place of the regexp operators like that, but correct me if I am wrong. I also am not sure if you can use eval with (), try using {} or " " instead.
-------------------------------------------------


davorg
Thaumaturge / Moderator

Nov 11, 2003, 5:19 AM

Post #3 of 4 (476 views)
Re: [clinton] using eval with regex's [In reply to] Can't Post

Your problem is due to the multiple levels of evaluation that is going on here. A good way to debug this kind of problem is to print out the code that you are going to evaluate.

Here's your existing code (slightly adjusted):

Code
#!/usr/bin/perl 

use strict;
use warnings;

$_ = $ARGV[0];

my $compare = <<COMPARE;
if ("$_" =~ /.*\Q$ARGV[1]\E.*/$ARGV[3]) {
"$_" =~ s/$ARGV[1]/$ARGV[2]/$ARGV[3];
}
else
{}
COMPARE

print "$compare\n";
eval($compare);
print $@;


And this produces the following output (the program is in old.pl):

Code
$ ./old.pl foo oo OO g 
if ("foo" =~ /.*oo.*/g) {
"foo" =~ s/oo/OO/g;
}
else
{}

Can't modify constant item in substitution (s///) at
(eval 1) line 2, at EOF


At this point it becomes (I hope) clear what is going on. As well as the various parts of the substitution operator, the $_ variable is also getting expanded. This means that the substitution is actually trying to change the string "foo" rather than the variable $_. This is illegal, hence the error that you see.

To avoid the error we need to prevent $_ from being expanded in the heredoc. The simplest way to do this is to escape it with a backslash. Here's the new version of the code:


Code
#!/opt/bin/perl 

use strict;
use warnings;

$_ = $ARGV[0];

my $compare = <<"COMPARE";
if (\$_ =~ /\Q$ARGV[1]\E/) {
\$_ =~ s/\Q$ARGV[1]\E/$ARGV[2]/$ARGV[3];
}
else
{}
COMPARE

print $compare, "\n";
eval $compare;
print "$@\n$_\n";

And running it (in new.pl) produces this:

Code
$ ./new.pl foo oo OO g 
if ($_ =~ /oo/) {
$_ =~ s/oo/OO/g;
}
else
{}


fOO


Which is, I think, what you wanted.

--
Dave Cross, Perl Hacker, Trainer and Writer
http://www.dave.org.uk/
Get more help at Perl Monks


clinton
Novice

Nov 11, 2003, 9:09 AM

Post #4 of 4 (474 views)
Re: [davorg] using eval with regex's [In reply to] Can't Post

Hi,

That worked perfectly. Thanks very much.

 
 


Search for (options) Powered by Gossamer Forum v.1.2.0

Web Applications & Managed Hosting Powered by Gossamer Threads
Visit our Mailing List Archives