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: $!";
}