#!/usr/bin/perl -w # # footnotes in perl # using two pass approach # # copyright 2008 by Andreas Romeyke (fa.romeyke@web.de) # # Competition of Linux Magazine 2008-10 to write a footnote sorter # in different languages. # # call "perl footnotes2.pl infile outfile outfile2" # # the first outfile contains the text with footnotes in ordered, the second in used order # # the script detects errors in indexing, print and ignores them ("[43242]" will be replaced by ""). # use strict; my $INPUT; my $infile; my $fh; my $filenames; my %hash; my $regex=qr/\[\d+\]/; if (@ARGV != 3) {die "\nwrong count of arguments,\ncall 'perl footnotes2.pl infile outfile outfile2'\n";} ($infile,$filenames->{'ordered'},$filenames->{'used'})=@ARGV; select STDOUT; $| = 1; # make unbuffered select STDERR; $| = 1; # make unbuffered sub sopen ($) { my $part=$_[0]; open ($fh->{$part}, '>', $filenames->{$part}) || die "can't open $filenames->{'$part'}:$!"; } sub sclose ($) { my $part=$_[0]; close($fh->{$part}) || die "can't close $filenames->{'$part'}:$!"; } sub subst ($$) { # lookup function, needed to add warnings if something wrong my ($part, $key)=@_; my $value = $hash{$part}{$key}; if (!defined $value) {print STDERR "Index $key not found in $part part\n"; return ""; } return $value; } sub process_line ($$) { # processes line and print result to special output my ($part, $line) = @_; my $FH=$fh->{$part}; $line=~s/($regex)/subst($part,$1)/ge; print $FH $line; } # pass 1, read file in, create index hash print "Pass 1..."; open ($INPUT, $infile) || die "can’t open $infile: $!"; { my $part = 'used'; while (<$INPUT>) { if ($part eq 'used' && (/^\@footnotes:$/)) { $part='ordered'}; map { $hash{$part}{$_} = "[".((keys %{$hash{$part}})+1)."]" } grep { $_=~/^$regex/ } split (/($regex)/); } } close($INPUT) || die "can’t close $infile: $!"; # pass 2, read file in, replace index and write out print "\nPass 2..."; open ($INPUT, '<', $infile) || die "can’t open $infile: $!"; sopen('ordered'); sopen('used'); while (<$INPUT>) { process_line('ordered', $_); process_line('used', $_); } sclose('ordered'); sclose('used'); close($INPUT) || die "can’t close $infile: $!"; print "\ndone.\n";