Passing in the replace string for a regex via the command line -HOW?

A

Anthony Roy

Hi all,

I have just come accross this little problem:

I am trying to pass in the find and replace values for a regex
substitution via the command lin, but I am not getting the expexted
result at all.

The perl program (attached) is:

------------------------------------
$in = shift;
$out = shift;
$string = shift;

$string =~ s/$in/$out/;
print $string;
------------------------------------

The command line used to call the script is:

perl rename.pl (\w+).old $1 abcd.old

I had expected the output to be: abcd

instead it gives: $1

Replacing the line "$string =~ s/$in/$out/;" with "$string =~
s/$in/$1/;" works as expected.

I presume that the $out is being expanded to $1, but the $1 is not then
being expanded itself.

Any idea how to get this to work as it should?

Thanks.
 
A

A. Sinan Unur

I am trying to pass in the find and replace values for a regex
substitution via the command lin, but I am not getting the expexted
result at all.

The perl program (attached) is:

------------------------------------
$in = shift;
$out = shift;
$string = shift;

$string =~ s/$in/$out/;
print $string;
------------------------------------

The command line used to call the script is:

perl rename.pl (\w+).old $1 abcd.old

What happens to $1 will depend very much on the shell you are using. You
might have to quote the arguments to get consistent behavior.
I had expected the output to be: abcd

instead it gives: $1

From perldoc perlop:

bracketing quotes, e.g., "s(foo)(bar)" or "s<foo>/bar/". A "/e"
will cause the replacement portion to be treated as a
full-fledged Perl expression and evaluated right then and there.
It is, however, syntax checked at compile-time. A second "e"
modifier will cause the replacement portion to be "eval"ed
before being run as a Perl expression.

Giving us:

#! /usr/bin/perl -T

use strict;
use warnings;

my ($in, $out, $string) = @ARGV;

$string =~ s/$in/$out/ee;

print "$string\n";

__END__

Note that this script will not run as it stands because of the -T switch
in the shebang line. You will need to decide what acceptable patterns
can be used as the replacement string and untaint them, following the
instructions in perldoc perlsec.

Or, you can remove the -T switch, but don't do that before you have read
perlsec and said out loud "I accept the possibility that this script can
be used to wipe away my life" :)

Sinan.
 
S

Shawn Corey

Anthony said:
Hi all,

I have just come accross this little problem:

I am trying to pass in the find and replace values for a regex
substitution via the command lin, but I am not getting the expexted
result at all.

The perl program (attached) is:

------------------------------------
$in = shift;
$out = shift;
$string = shift;

$string =~ s/$in/$out/;
print $string;
------------------------------------

The command line used to call the script is:

perl rename.pl (\w+).old $1 abcd.old

I had expected the output to be: abcd

instead it gives: $1

Replacing the line "$string =~ s/$in/$out/;" with "$string =~
s/$in/$1/;" works as expected.

I presume that the $out is being expanded to $1, but the $1 is not then
being expanded itself.

Any idea how to get this to work as it should?

Thanks.

#!/usr/bin/perl

use strict;
use warnings;

my $in = shift;
my $out = shift;
my $string = shift;

eval "\$string =~ s/$in/$out/;";
print $string, "\n";

__END__

You have to eval the string '$1' to code. See perldoc -f eval

--- Shawn
 
T

Tad McClellan

Anthony Roy said:
I am trying to pass in the find and replace values for a regex
substitution via the command lin,
$string =~ s/$in/$out/;
perl rename.pl (\w+).old $1 abcd.old

I had expected the output to be: abcd

instead it gives: $1

Any idea how to get this to work as it should?


$string =~ s/$in/$out/ee;


See also:

perldoc -q strings

How can I expand variables in text strings?
 
B

Brian McCauley

Anthony said:
A. Sinan Unur wrote:
...



Excellent - I knew there would be a simple solution. Thanks.

But this means the caller must pass the replacement as a Perl expression
rather than as a a double-quotish string.

If the caller is to pass a Perl expression it's simpler just to pass the
whole s/// as one argument rather than two.

eval $subst for $string;

If you insist on having in/out as separate variables then I'd suggest
the the chomp/eval/here-doc solution as described in my lightning talk
at YAPC::Europe::2004 where I pleaded for this question (and honest
answers to it) to be put in the FAQ.
 
A

A. Sinan Unur

....

If you insist on having in/out as separate variables then I'd suggest
the the chomp/eval/here-doc solution as described in my lightning talk
at YAPC::Europe::2004 where I pleaded for this question (and honest
answers to it) to be put in the FAQ.

Argh! I do remember you making this point at least once before. I went
back and re-read your talk. It makes sense to me. I am sorry I forgot
about it.

I took me a while to re-locate it (apparently, my skills at using
Google's search interface are not that great), so I am posting the
reference here for others' benefit:

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

Sinan.
 

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

Forum statistics

Threads
474,266
Messages
2,571,087
Members
48,773
Latest member
Kaybee

Latest Threads

Top