use Regexp::Common; while( $html =~ s/($RE{balanced}{-parens=>'<>'})// ) { $tags{$-[0]} .= $1; } $html =~ s/foo/bar/g; foreach my $point (sort {$b<=>$a} keys (%tags)) { substr($html, $point, 0 ) = $tags{$point}; }