Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

ARGV interpretation in s///

3 views
Skip to first unread message

Just in

unread,
Sep 29, 2005, 12:01:00 AM9/29/05
to
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


Paul Lalli

unread,
Sep 29, 2005, 8:19:42 AM9/29/05
to
Just in wrote:
> 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

Tad McClellan

unread,
Sep 29, 2005, 8:22:56 AM9/29/05
to
Just in <goth...@hotmail.com> wrote:

> 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?


--
Tad McClellan SGML consulting
ta...@augustmail.com Perl programming
Fort Worth, Texas

Brian McCauley

unread,
Sep 29, 2005, 8:25:26 AM9/29/05
to
Just in wrote:

> 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.

Please see my "History of a FAQ" lightning talk about this question...

http://birmingham.pm.org/talks/faq/Hello.html

Tad McClellan

unread,
Sep 29, 2005, 9:39:16 AM9/29/05
to
Paul Lalli <mri...@gmail.com> wrote:

> 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 <* .*>';

??

Paul Lalli

unread,
Sep 29, 2005, 3:26:17 PM9/29/05
to
Tad McClellan wrote:
> Paul Lalli <mri...@gmail.com> wrote:
>
> > 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?

> 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

Brian McCauley

unread,
Sep 30, 2005, 12:21:08 PM9/30/05
to

Tad McClellan wrote:

> Just in <goth...@hotmail.com> wrote:
>
>>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

0 new messages