or, a little more concisely...
$s =~ s/a/B/ for(1..3);
| [reply] [d/l] |
>perl -wMstrict -le
"my $x = 'aBaCaDaEaFa';
$x =~ s/a/aa/ for 1 .. 3;
print $x;
"
If I run this code, I might expect 'aaBaaCaaDaEaFa' to be printed, but I get 'aaaaBaCaDaEaFa' instead. This is because the regex of the substitution does not 'remember' its position in the string being searched, but instead starts from the beginning of the string on each invocation. So, if the substituted portion of the string contains anything that may be matched by the regex, then it, and not anything further along in the string, is what will be (repeatedly) replaced.
jwkrahn's reply Re: Does Perl support a given number of replacements ? shows a way around this.
Update: Improved first example and changed pertinent discussion, removed a second example as no longer offering greater clarity. | [reply] [d/l] [select] |
Quite right!!
I experimented with the g option, \G and pos() but they don't work with substitutions as they do with matches and in the end I couldn't find any RE based solution simpler than jwkrahn's that handles replacements that match the search pattern.
But I find REs difficult enought to understand without embeded code, so I came up with the following alternative which may have merit in some situations. It works for the examples you provided but it's not obvious that its doing replacement and the third argument to split is one more than the number of replacements, so it's certainly not ideal.
my $s1 = 'abaacaa';
my $s2 = 'abcdefg';
$s1 = join('aa', split('a', $s1, 4));
$s2 = join('aa', split(/[abcedfg]/, $s2, 4));
print "$s1\n";
print "$s2\n";
| [reply] [d/l] |
Wonderful !!!
That's exactly what I was thinking of :))
Thanks.
| [reply] |
A nice one.
I use a similar code with awk. I had the impression that Perl might have a ready-made construct that works right out of the box.
Thanks. | [reply] |
There is a catch though. If 'B' contains 'a', (or the replacement of an 'a' to a 'B' creates a new 'a'), this doesn't quite do what you want. A simple case, assume 'a' is '\w' and 'B' is just 'B'. Then
$_ = 'pqrstuvw';
my $i = 3;
while($i) {
$i--;
s/\w/B/;
}
print "$_\n";
__END__
Bqrstuvw
| [reply] [d/l] |