JonHodgson
asked on
PERL search-and-replace using variables [ s/$search/$replace/ ] and backreferences
I need to load a list of search-and-replace patterns (with backreferences) in from a config file and apply them to a series of strings. I can't figure out how to do a search-and-replace with backreferences using variables.
This is the RESULT i'm trying to achieve (shown first without using variables):
BEFORE: [foo1bar]
AFTER: [foo---bar]
BUT, I need to achieve the same result using variables.
I tried the following:
BEFORE: [foo1bar]
AFTER: [$1---bar]
I can't figure out how to get $1 to expand to the backreferenced value.
I tried playing with /e & /ee modifiers but those didn't work. Please help!
This is the RESULT i'm trying to achieve (shown first without using variables):
use strict;
my $string='foo1bar';
print "BEFORE: [$string]\n";
$string =~ s/(.*)\d/$1---/;
print "AFTER: [$string]\n";
which works perfectly:BEFORE: [foo1bar]
AFTER: [foo---bar]
BUT, I need to achieve the same result using variables.
I tried the following:
use strict;
my $string='foo1bar';
my $search='(.*)\d';
my $replace='$1---';
print "BEFORE: [$string]\n";
$string =~ s/$search/$replace/;
print "AFTER: [$string]\n";
But that did not work as I hoped:BEFORE: [foo1bar]
AFTER: [$1---bar]
I can't figure out how to get $1 to expand to the backreferenced value.
I tried playing with /e & /ee modifiers but those didn't work. Please help!
ASKER
farazanj,
Thank you very much. You've gotten me closer to my ultimate solution. I didn't realize in this case there would be a difference between single & double quotes, as I assumed the variable substitution occurred at the time of assignment rather than at the time of evaluation.
I still need to achieve my ultimate goal of reading these patterns from a config file. It's behaving like my single-quote example and i'm not sure how to make it behave like your double-quote version:
SEARCH: [(.*)\d]
REPLACE: [$1---]
BEFORE: [foo1bar]
AFTER: [$1---bar]
If I can get this to work this will solve my problem. Thanks.
Thank you very much. You've gotten me closer to my ultimate solution. I didn't realize in this case there would be a difference between single & double quotes, as I assumed the variable substitution occurred at the time of assignment rather than at the time of evaluation.
I still need to achieve my ultimate goal of reading these patterns from a config file. It's behaving like my single-quote example and i'm not sure how to make it behave like your double-quote version:
use strict;
my %config;
open(CONFIG, "<subtest.cfg");
# subtest.cfg contains: (whitespace is 2 tabs)
# (.*)\d $1---
while(<CONFIG>){
chomp;
s/#.*//; # No comments
s/^\s+//; # No leading whitespace
s/\s+$//; # No trailing whitespace
next unless length; # Skip blank lines
my ($search,$replace) = split("\t\t",$_,2);
$config{$search}=$replace;
}
close(CONFIG);
my $string='foo1bar';
foreach my $search (keys %config) {
my $replace=$config{$search};
print "SEARCH: [$search]\n";
print "REPLACE: [$replace]\n";
print "BEFORE: [$string]\n";
$string =~ s/$search/$replace/;
print "AFTER: [$string]\n\n";
}
It's outputting incorrectly:SEARCH: [(.*)\d]
REPLACE: [$1---]
BEFORE: [foo1bar]
AFTER: [$1---bar]
If I can get this to work this will solve my problem. Thanks.
Need your input file(s).
ASKER
farzanj,
My code example showed the content of my input file in the comment where I opened the file:
# subtest.cfg contains: (whitespace is 2 tabs)
# (.*)\d $1---
It's just:
(.*)\d<tab><tab>$1---
(That's the same search and replace as before, but with 2 tabs as the delimiter)
My code example showed the content of my input file in the comment where I opened the file:
# subtest.cfg contains: (whitespace is 2 tabs)
# (.*)\d $1---
It's just:
(.*)\d<tab><tab>$1---
(That's the same search and replace as before, but with 2 tabs as the delimiter)
ASKER
Here's the file in case that's easier for you.
subtest.cfg.txt
subtest.cfg.txt
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
farzanj,
That worked! Before I close this out and assign you all the points, can you please briefly explain WHY your changes worked?
This will help me and others not have this issue in the future.
Thanks,
Jon
That worked! Before I close this out and assign you all the points, can you please briefly explain WHY your changes worked?
This will help me and others not have this issue in the future.
Thanks,
Jon
$replace='"$1---"';
$string =~ s/$search/$replace/ee ;
$string =~ s/$search/$replace/ee ;
ASKER
Hi ozo/farzanj,
I wasn't asking which lines he made changes on. I already figured that out with diff.
I mean an EXPLANATION, in words, as to why that syntax was needed. I'm trying to LEARN why this worked rather than just cut-and-pasting the answer.
Thanks
I wasn't asking which lines he made changes on. I already figured that out with diff.
I mean an EXPLANATION, in words, as to why that syntax was needed. I'm trying to LEARN why this worked rather than just cut-and-pasting the answer.
Thanks
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Farzanj,
Thanks so much for your solution and the explanation. I've awarded you all the points.
- Jon
Thanks so much for your solution and the explanation. I've awarded you all the points.
- Jon
my $replace='$1---';
to
my $replace="$1---";