if you want to check whats the fastest way to replace a string in
Perl you could use the
Benchmark-Module.I compared 4 different ways :
#!/usr/bin/perl
use strict;
use warnings;
use Benchmark qw(:all) ;
use Inline 'C';
my $teststring;
#check result :
$teststring = "teststring1"; $teststring =~ s/1/2/g; print $teststring.$/;
$teststring = "teststring1"; $teststring =~ s/1/2/go; print $teststring.$/;
$teststring = "teststring1"; $teststring =~ tr/1/2/; print $teststring.$/;
$teststring = "teststring1"; $teststring = replace($teststring,"1","2"); print $teststring.$/;
$teststring = "teststring1"; $teststring = repl_str($teststring,"1","2"); print $teststring.$/;
#test one
cmpthese(-4, {
'regex_normal' => sub {$teststring = "teststring1"; $teststring =~ s/1/2/g; },
'regex_optimised' => sub {$teststring = "teststring1"; $teststring =~ s/1/2/go; },
'translate' => sub {$teststring = "teststring1"; $teststring =~ tr/1/2/; },
'perl_sub' => sub {$teststring = "teststring1"; $teststring = replace($teststring,"1","2"); },
'C_replace_string' => sub {$teststring = "teststring1"; $teststring = repl_str($teststring,"1","2"); },
});
#test two
cmpthese(-4, {
'regex_normal' => sub {$teststring = "teststring1stringxstring"; $teststring =~ s/string/test/g; },
'regex_optimised' => sub {$teststring = "teststring1stringxstring"; $teststring =~ s/string/test/go; },
'translate' => sub {$teststring = "teststring1stringxstring"; $teststring =~ tr/string/test/; },
'perl_sub' => sub {$teststring = "teststring1stringxstring"; $teststring = replace($teststring,"string","test"); },
'C_replace_string' => sub {$teststring = "teststring1stringxstring"; $teststring = repl_str($teststring,"string","test"); },
});
sub replace {
my $string = shift;
my $old = shift;
my $new = shift;
my $pos = index($string, $old);
while ( $pos > -1 ) {
substr( $string, $pos, length( $old ), $new );
$pos = index( $string, $old, $pos + length( $new ));
}
return($string);
}
__END__
__C__
char* repl_str(const char *str, const char *old, const char *new){
char *ret, *r;
const char *p, *q;
size_t oldlen = strlen(old);
size_t count, retlen, newlen = strlen(new);
if (oldlen != newlen) {
for (count = 0, p = str; (q = strstr(p, old)) != NULL; p = q + oldlen)
count++;
retlen = p - str + strlen(p) + count * (newlen - oldlen);
} else
retlen = strlen(str);
if ((ret = malloc(retlen + 1)) == NULL)
return NULL;
for (r = ret, p = str; (q = strstr(p, old)) != NULL; p = q + oldlen) {
ptrdiff_t l = q - p;
memcpy(r, p, l);
r += l;
memcpy(r, new, newlen);
r += newlen;
}
strcpy(r, p);
return ret;
}
the result looks like:
teststring2
teststring2
teststring2
teststring2
teststring2
Rate perl_sub C_replace_string regex_normal regex_optimised translate
perl_sub 632214/s -- -68% -68% -70% -91%
C_replace_string 1961177/s 210% -- -2% -8% -71%
regex_normal 1999403/s 216% 2% -- -7% -71%
regex_optimised 2142180/s 239% 9% 7% -- -69%
translate 6843359/s 982% 249% 242% 219% --
Rate perl_sub regex_normal regex_optimised C_replace_string translate
perl_sub 430150/s -- -50% -50% -57% -92%
regex_normal 861549/s 100% -- -0% -14% -85%
regex_optimised 862213/s 100% 0% -- -14% -85%
C_replace_string 998062/s 132% 16% 16% -- -82%
translate 5603343/s 1203% 550% 550% 461% --
Always check you sub results (Line 1-5) and make more test cases,
at the first case (Line 6) we see that for single character the best solution is to use
regex.If you want to replace a longer string better use a
C function.But in both cases its better to use the /o flag for regex to optimize, but then you cant interpolate a string in to the regex.And if you only want to replaxe use
tr its the fastest.