#!/usr/bin/perl
# $Id: replace-template-file.pl,v 1.4 2007-07-17 06:19:13 steve Exp $
#
#
replace-template-file
# This script is used to replace part of a file -- usually HTML --
# with the contents of a template. The first and last lines
# of the template file are matched, and everything between the first
# match of the first line to the first match of the last line is
# replaced by the contents of the template. Usually the template
# is an HTML element with a distinctive id or class attribute.
### Open Source/Free Software license notice:
# The contents of this file may be used under the terms of the GNU
# General Public License Version 2 or later (the "GPL"). The text
# of this license can be found on this software's distribution media,
# or obtained from www.gnu.org/copyleft/gpl.html
### :end license notice ###
if (! @ARGV) {
print "Usage: $0 template file...\n";
exit 0;
}
my $bak = ".~bak~";
### Read and analyse the template file
my $template_file = $ARGV[0]; shift @ARGV;
if (! open(IN, $template_file)) {
die "Template file '$template_file' does not exist";
}
my $template_text = "";
my $template_first = "";
my $template_last = "";
while () {
$template_text .= $_;
$template_last = $_;
if ($template_first eq "") { $template_first = $_; }
}
close IN;
### If no input files, just print the analysis of the template.
if (! @ARGV) {
print "No target files specified; just analyzing the template:\n";
print $template_first;
print "...\n";
print $template_last;
exit 0;
}
### Loop through the input files.
my $n_replaced = 0;
my $n_failed = 0;
while (@ARGV) {
my $infile = $ARGV[0]; shift @ARGV;
# Skip directories and backup files
next if (-d $infile);
next if ($infile =~ /\~$/);
# Read the input file (only once)
my $content = read_file($infile);
if ($content eq "") {
print STDERR "*** Input file '$infile' missing or empty: skipping\n";
next;
}
# skip files that already have the most recent template inserted.
# Note that the way we do the substitution is exceedingly crude;
# in particular, it matches to the last instance of the last line,
# instead of the first, so it had better be unique.
# === this needs to be fixed!! ===
my $insert = $template_text;
my $first = $template_first;
my $last = $template_last;
$first = quotemeta($first);
$last =~ s/\n//s; # take the \n off $last...
# it interacts w\ quotemeta
$last = quotemeta($last);
my $inserted = quotemeta($insert);
$last .= "\n"; # ...put the \n back
if ($content =~ /$inserted/s) {
print STDERR "-- Input file '$infile' is up to date: skipping.\n"
if $verbose;
next;
} elsif ($content =~ /$first.*$last/s) {
# === This will do horrible things to a file that contains
# more than one line that matches $last!!
# Really ought to cycle through the lines and do it carefully.
$content =~ s/$first.*$last/$insert/s;
$n_replaced ++;
} else {
print STDERR "** $template_file not found in input file '$infile'.\n";
$n_failed ++
}
# Save a backup file
`[ -f $infile$bak ] && rm $infile$bak`;
`mv $infile $infile$bak`;
# Output the modified file
print_file($infile, $content);
# Make it executable if the backup was
`[ -x $infile$bak ] && chmod +x $infile`;
}
print STDERR " $n_replaced replaced; $n_failed failed $template_file\n";
exit 0;
#########################################################################
### read_file($pathname)
# Read a file into a string. Return null if the file doesn't exist.
sub read_file {
my ($fn) = (@_);
my $s = '';
if (open(IN, $fn)) {
while () { $s .= $_; }
close IN;
}
return $s;
}
### print_file($pathname, $string)
# print a string into a file. If the file was a symlink,
# remove it to ensure that we don't clobber the original.
sub print_file {
my ($fn, $s) = (@_);
if (-l $fn) { unlink($fn); }
if (open(OUT, ">$fn")) {
print OUT $s;
print OUT "\n" unless $s =~ /\n$/s;
close OUT;
}
}
#########################################################################