The problem is that your iterator gets reset every time you change your string, so you end up accumulating an infinite number of your modifications in your first match. A much cleaner way of accomplishing this would be to use the e modified -- see Search and replace in perlretut. You can then get it all done in one clean shot:
my $counter = 0; $str =~ s/<tag1[^>]*>\s*<tag2>\s*<tag3>[^<]*\K(?=<\/endtag3>)/sprintf +" [ $c-%d]", ++$counter/egsi;
I've used the \K control character (Character Classes and other Special Escapes) and a look-ahead (Looking ahead and looking behind) to save from having to put back unnecessarily removed material. It also makes the result much clearer, I think.
As a side note, you should not use $a and $b as normal variables, since they have special meaning in a sorting context; see $a. It's usually considered poor form to use single character variable names, except in some very specific, common scenarios, e.g. $i, $j... for counters and $x, $y... for coordinates.
In reply to Re: while loop w/match is hanging
by kennethk
in thread while loop w/match is hanging
by Anonymous Monk
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |