perl -e "$_='aaaaaaaaaa'; substr($_,0,-4)='X' x (length($_) -4); print" #### perl -e "$_='1234567890'; substr($_,0,-4, 'X' x (length($_) - 4)); print" #### use Benchmark; my $string = "1234567890"; timethese(-5, { 'Regexp' => sub { $string =~ s/(.*?)(....)$/("X" x length($1)).$2/e; }, 'Regexp D&P' => sub { $string =~ s/.(?!.{0,3}$)/x/g; }, 'Substring' => sub { $string = length substr($string,0,-4). substr($string,- 4) }, 'mysubstr' => sub { substr($string,0,-4)='X' x (length($string) - 4) }, 'fourarg' => sub { substr($string, 0, -4, 'X' x (length($string) - 4)) } }); Benchmark: running Regexp, Regexp D&P, Substring, fourarg, mysubstr, each for at least 5 CPU seconds... Regexp: 6 wallclock secs ( 5.35 usr + 0.00 sys = 5.35 CPU) @ 40933.99/s (n=218915) Regexp D&P: 5 wallclock secs ( 5.18 usr + 0.00 sys = 5.18 CPU) @ 90739.67/s (n=469850) Substring: 6 wallclock secs ( 5.19 usr + 0.00 sys = 5.19 CPU) @ 316184.66/s (n=1640366) fourarg: 6 wallclock secs ( 5.10 usr + 0.00 sys = 5.10 CPU) @ 370755.39/s (n=1890111) mysubstr: 6 wallclock secs ( 5.39 usr + 0.00 sys = 5.39 CPU) @ 271099.83/s (n=1460957)