This has probably been done a million times, but whatever. I crafted it for use in Parrot's Configure.pl script (see my home node). The function takes one parameter--a filename with dots replaced by underscores--and reads in $filename.in. It then does all the substitutions necessary, s/_/./g's the filename, and writes the result out.
sub buildfile { my($filename)=shift; local $/; open(IN, "<$filename.in") or die "Can't open $filename.in: $!"; my $text=<IN>; close(IN) or die "Can't close $filename.in: $!"; $text =~ s/\$\{(\w+)\}/$c{$1}/g; $filename =~ s/_/./; #config_h => config.h open(OUT, ">$filename") or die "Can't open $filename: $!"; print OUT $text; close(OUT) or die "Can't close $filename: $!"; }