ARGV interpretation in s///

J

Just in

I'm trying to write regexp search and replace strings on the command line
and have the program I'm calling use them in a substitution. Problem is that
the $[0-9] variables are not being interpreted the way I want them to be.

Heres what I am doing on my Linux box:-

<OUTPUT>
%> try.pl -f to.txt -s 'add (\w+) minus' -r 'FOO$1BAR'
FOO$1BAR
FOO$1BAR
%>
</OUTPUT>

<CODE>
#!/usr/bin/perl
use strict;
use warnings;
use Getopt::Std;

# Variable declaration
my $Search = my $Replace = my $File = '';

# Process @ARGV
getopts('f:hr:s:');
our($opt_f, $opt_r, $opt_s);

$opt_f ? $File = $opt_f : &DisplayHelp();
$opt_r ? $Replace = $opt_r : &DisplayHelp();
$opt_s ? $Search = $opt_s : &DisplayHelp();

open(FILE, $File) or die "Can't open $File:- $!";
while(<FILE>)
{
s/$Search/$Replace/;
print;
}
close FILE;

sub DisplayHelp
{
print "To be defined\n";
exit 0;
}
</CODE>

How can I achieve the desired interpretation of $1? Single quotes and double
quotes don't help, nor does qr//

Cheers

Just in
 
P

Paul Lalli

Just said:
I'm trying to write regexp search and replace strings on the command line
and have the program I'm calling use them in a substitution. Problem is that
the $[0-9] variables are not being interpreted the way I want them to be.

You have mis-diagnosed your problem. The fact that you are reading
your replacement string from the command line is irrelevant to the
issue at hand. Your goal is to get Perl to understand that a string
containing the characters '$1' should in fact be evaluated as
containing the string residing in the variable $1.

As I was playing with a condensed version of your script, I eventually
stumbled on to the answer. Unfortunately, I do not at all understand
the answer. I found that if I add double quotes surrounding the
Replacement string, and use a double /e modifier on the regexp, then $1
becomes correctly interpolated.

I'm hoping someone else in this group can explain to me why this works,
or better yet, why *doesn't* a simple single /e without the extra
double quotes, or even a /ee without the extra double quotes. Why are
the two evals and the double quotes all necessary?

Here is a short-but-complete script that illustrates the solution I
found:

#!/usr/bin/perl
use strict;
use warnings;

my $Replace = 'FOO$1BAR';
my $Search = 'add (\w+) minus';

$Replace = qq{"$Replace"};

while(<DATA>){
if (s/$Search/$Replace/ee) {
print;
}
}

__DATA__
add stuff minus
add other_stuff minus


Paul Lalli
 
T

Tad McClellan

Just in said:
Problem is that
the $[0-9] variables are not being interpreted the way I want them to be.

s/$Search/$Replace/;

How can I achieve the desired interpretation of $1?


$Replace = qq("$Replace");
s/$Search/$Replace/ee;


See also:

perldoc -q expand

How can I expand variables in text strings?
 
T

Tad McClellan

Paul Lalli said:
I'm hoping someone else in this group can explain to me why this works,
or better yet, why *doesn't* a simple single /e without the extra
double quotes, or even a /ee without the extra double quotes. Why are
the two evals and the double quotes all necessary?


The replacement string part of s/// is double quotish (by default),
ie. with implied double quotes.

So, (with the implied quotes shown) it looks like this to perl:

"$Replace"

perl does the indicated interpolation to determine the string to
use as the replacement.


Using the s///e modifier changes the above mentioned default so
that the replacement part is code rather than a string.

In that case, perl sees:

$Replace

so it evaluates that (simple) expression, no interpolation going on here.


With s///ee, the 1st eval sees:

$Replace

as in the s///e case above. After evaluating that, the 2nd eval sees:

FOO$1BAR

bareword, variable, bareword. And confusion ensues.


So, adding the double quotes to the value in $Replace would make
the 2nd eval see:

"FOO$1BAR"

perl does the indicated interpolation to determine the string to
use as the replacement.



Note that, though it doesn't apply in this case since the values
are coming from the command line anyway, but what would the
2nd eval is s///ee see (and evaluate) if $Replace should
ever get a value like:

$Replace = 'unlink <* .*>';

??
 
P

Paul Lalli

Tad said:
With s///ee, the 1st eval sees:

$Replace

as in the s///e case above. After evaluating that, the 2nd eval sees:

FOO$1BAR

bareword, variable, bareword. And confusion ensues.


So, adding the double quotes to the value in $Replace would make
the 2nd eval see:

"FOO$1BAR"

perl does the indicated interpolation to determine the string to
use as the replacement.

Tad,

Thank you very much for the very detailed explanation. I believe I now
understand the situation.

Much obliged,
Paul Lalli
 
B

Brian McCauley

Tad said:
Just in said:
Problem is that
the $[0-9] variables are not being interpreted the way I want them to be.
s/$Search/$Replace/;

How can I achieve the desired interpretation of $1?

$Replace = qq("$Replace");
s/$Search/$Replace/ee;

Once again, can I ask people not post this "simple, obvious, and
wrong"[1] response to this question without mentioning the hazards of
eval() and also pointing out how to avoid the problem with " characters
in $Replace.

[1] http://birmingham.pm.org/talks/faq/Answer.html
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,482
Members
44,901
Latest member
Noble71S45

Latest Threads

Top