Following up from an earlier question on extracting the n'th regex match, I now need to substitute the match, if found.
I thought that I could define the extraction subroutine and call it in the substitution with the /e
modifier. I was obviously wrong (admittedly, I had an XY problem).
use strict;
use warnings;
sub extract_quoted { # à la codaddict
my ($string, $index) = @_;
while($string =~ /'(.*?)'/g) {
$index--;
return $1 if(! $index);
}
return;
}
my $string = "'How can I','use' 'PERL','to process this' 'line'";
extract_quoted ( $string, 3 );
$string =~ s/&extract_quoted($string,2)/'Perl'/e;
print $string; # Prints 'How can I','use' 'PERL','to process this' 'line'
There are, of course, many other issues with this technique:
- What if there are identical matches at different positions?
- What if the match isn't found?
In light of this situation, I'm wondering in what ways this could be implemented.
Or you can do something as this
A little ugly the "global" $cont variable, that could be polished, but you get the idea.
Update: a more compact version:
Reworking an answer to an earlier question, match n-1 times and then replace the next. Memoizing patterns spares poor Perl having to recompile the same patterns over and over.
For example
outputs
See perldoc perlvar:
Output:
Of course, you need to decide what happens if an invalid
$index
is passed or if the required match is not found. I just return the original string in the code above.If the regex isn't too much more complicated than what you have, you could follow a
split
with an edit and ajoin
:EDIT: leonbloy came up with this solution first. If your tempted to upvote it, upvote leonbloy's first.
Somewhat inspired by leonbloy's (earlier) answer: