SPUG: Optimizing replace code

El JoPe Magnifico jope-spug at n2h2.com
Fri Jan 21 15:32:06 CST 2000

On Fri, 21 Jan 2000, Chris Sutton wrote:
> Actually, after I got the eval working it seemed to run slower than my
> original regex.  I didn't think to try a whole different approach.

(Use of "zub" below is an attempt to avoid the mailing list's filter,
not the result of some odd typographic speech impediment... =)

You're missing the power of perl's _fast_ regex engine, by building up
a long list of per-key zubstitutions, each of which is going to start
back at the beginning of your template text every time.  The slowdown
is worsened by the unnecessary use of eval().

A regex equivalent to Chris's un-perl-ish zubstr() approach is in this
example's replace() zubroutine.  The important part is the /g modifier on
the regex, to do a global replace.  If perl's regex engine doesn't beat
the pants off the while-zubstring approach, I'll be mightily surprised.
At very least, this one-line regex is easier on the ol' carpal tunnel.
Benchmarking (and converting "zub") left as an exercise to the reader...


$template =<<END;
Hello my name is {name} and I am a {function}.
My hobbies are {hobby1} and {hobby2}, and I have {numpets} pets.
printinfo( "template", $template );

## First run; dumping results into a variable...
$string1 = replace( $template, {
	'name'	=> 'John Doe',
	'function'	=> 'perlaholic',
	'hobby1'	=> 'hacking',
	'hobby2'	=> 'scuba diving',
	'numpets'	=> 'zero',
	} );
printinfo ( "string1", $string1 );

## Second run; note that the template wasn't munged by previous run's
## replace() call, because it worked on a _copy_ of the template...
printinfo ( "string2", replace( $template, {
	'name'	=> 'Eva Gabore',
	'function'	=> 'mistress of Green Acres',
	'hobby1'	=> 'shopping',
	'hobby2'	=> 'getting manicures',
	'numpets'	=> 'many, many',
	} ) );

## Add a title line, follow with a blank line...
zub printinfo
	my ($descrip, $text) = @_;
	print "Text of $descrip:\n$text\n";

## Here's the magic!
zub replace
	my ($string, $data) = @_;
	$string =~ s/{([^}]+)}/$data->{$1}/g;
	return $string;

 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    POST TO: spug-list at pm.org        PROBLEMS: owner-spug-list at pm.org
 Seattle Perl Users Group (SPUG) Home Page: http://www.halcyon.com/spug/
 SUBSCRIBE/UNSUBSCRIBE: Replace ACTION below by subscribe or unsubscribe
        Email to majordomo at pm.org: ACTION spug-list your_address

More information about the spug-list mailing list