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

I was recently trying to pass the $1 name to a search and replace as part of the value of another variable.

Example:
$search = "(.*)\d\d\d\d\d\d.txt";
# $search should match to some_string200912.txt
$replace = "some_value_$1";

$to_modify = "some_string200912.txt";

$to_modify =~ s/$replace/$search/g;

If I do:
print $1; # This contains the characters captured in the parantheses (some_string)

But the value of $to_modify is just "some_value_" where I would be hoping for "some_value_some_string"

The search and replace strings are being fed to the script through a delimited config file that is used to assign variables.

I worked around it but found it peculiar. Right now I'm thinking that the value of $1 in the variable value ($replace) is that at the time in which the variable was initialized and thus was empty and that THAT $1 does not get re-initialized to the value in the parantheses at the time that the regex search and replace is run. Does that sound right or is there something else going on?

Thanks for any feedback. BTW using perl 5.8.8 on HP-UX 11.1
  • Comment on Passing $1 as part of a variable value to a regex search and replace

Replies are listed 'Best First'.
Re: Passing $1 as part of a variable value to a regex search and replace
by johngg (Canon) on Dec 05, 2009 at 20:01 UTC

    Part of your problem is you are using double-quotes when you should be using single-quotes so that, for instance, the $1 isn't interpolated at the time you initialise the $replace variable. Secondly, you need to use the e flag rather than the g flag because you need to execute a bit of code in your replacement part. In fact you need to use a double ee so that execution is done twice, first to interpolate the $replace variable into the "replace" term and second to interpolate again to get what was captured in $1. Thirdly, you have the terms of the substitution round the wrong way; "search" first, "replace" second.

    $ perl -le ' > $search = q{(.*)\d{6}\.txt$}; > $replace = q{ qq{XXXX_$1} }; > $to_modify = q{AAAA200912.txt}; > print $to_modify; > $to_modify =~ s/$search/$replace/ee; > print $to_modify;' AAAA200912.txt XXXX_AAAA

    I hope this is helpful.

    Cheers,

    JohnGG

      Thanks! It does help, I need to spend some more time with the regex chapter...
Re: Passing $1 as part of a variable value to a regex search and replace
by AnomalousMonk (Archbishop) on Dec 05, 2009 at 23:32 UTC
    Also see ikegami's many patient replies to eval problem and the other replies and links therefrom.
Re: Passing $1 as part of a variable value to a regex search and replace
by Marshall (Canon) on Dec 06, 2009 at 17:55 UTC
    I don't see the need to mess around with this $1 variable.
    I would use list slice to eliminate that. This is a powerful technique.

    Maybe I'm not getting the gist of the requirement, but it appears that you want the alpha stuff before the numbers start in two vars and want to modify a var based upon that. I think the code below could be generalized into a looping construct.

    #!/usr/bin/perl -w use strict; #this gets chars until first digit... my $search = "some_string200912.txt"; my $alpha1 = ($search =~ m/(.*?)\d+.txt/)[0]; #this gets chars until first digit... my $to_modify = "some_value200912.txt"; my $alpha2 = ($to_modify =~ m/(.*?)\d+.txt/)[0]; #this modifies (assigns new value to $to_modify) $to_modify = "$alpha2"."_"."$alpha1"; print "$to_modify\n"; __END__ prints: some_value_some_string
    Update:

    if the list slice on the right hand side offends you, put the left hand side into list context like this:

    #!/usr/bin/perl -w use strict; #this gets chars until first digit... my $search = "some_string200912.txt"; (my $alpha1) = $search =~ m/(.*?)\d+.txt/; #this gets chars until first digit... my $to_modify = "some_value200912.txt"; (my $alpha2) = $to_modify =~ m/(.*?)\d+.txt/; #this modifies (assigns new value to $to_modify) $to_modify = "$alpha2"."_"."$alpha1"; print "$to_modify\n"; __END__ prints: some_value_some_string