#!/usr/local/dist/bin/perl # # Dieses Programm sucht alle Literaturverweise in saemtlichen # LaTeX Dateien des aktuellen Verzeichnisses. Anhand der # Environment-Variable $BIBINPUTS findet es die dazugehoerigen # *.bib Dateien und erzeugt eine neue Bibliotheksdatei mit Namen # main.bib im aktuellen Verzeichnis. Falls hier eine solche Datei # schon existiert, so kann man den Namen der neuen Bibliotheksdatei # dem Programm auch als Switch mitgeben. ## Argumente bearbeiten ## Aktuelle Kommandozeilenparameter in $argv ablegen $argv = join(' ',@ARGV); ## Versionsnummer, Patchlevel und Erscheinungsdatum $PATCHLEVEL = "1a"; $VERSION = "97"; $RELDATE = "(Sep 29, 1997)"; $MakebibV_SHORT = $VERSION . '.' . "$PATCHLEVEL"; $MakebibVERSION = $MakebibV_SHORT . ' ' . $RELDATE; ## Hinweise zum Author $AUTHORADDRESS = "http://www.informatik.tu-muenchen.de/~allgeyer/index.html"; ## Name der neuen *.bib Datei $newbibfile = "main.bib"; ## Parameter aufloesen while ($ARGV[0] =~ /^-/) { $_ = shift; ## Debugging gewuenscht if (/^-debug$/) { $DEBUG = 1; } ## -newbibfile (file) wurde spezifiziert: elsif (/^-newbibfile$/) { $_ = shift; ((($newbibfile) = /^(.+)$/) || print "\nUnrecognised value for -newbibfile: $_\n" && &usage && die); } ## -h(elp) wurde eingegeben: elsif (/^-h(elp)?$/) { &usage; exit 0; } ## Kein bekannter Parameter? else { &usage; die "Unrecognised switch: $_\n"; } ## end (if) } ## end (while) ## Hole $HOME aus der Environment Variable ## und erweitere @INC damit push(@INC,$ENV{'HOME'}); $HOME = $ENV{'HOME'}; ## Statusausgabe print "Running \'makebib.pl $argv\': .."; ## Hole $BIBINPUTS aus der Environment Variable if ( $ENV{'BIBINPUTS'} eq '' ) { $BIBINPUTS = '.'; } else { $BIBINPUTS = $ENV{'BIBINPUTS'}; } ## end (if) ## Aktuelles Verzeichnis nach LaTeX Dateien durchsuchen @texfiles = glob ("*.tex"); foreach $texfile (@texfiles) { ## Debugging: print "\nTexfile found: $texfile\n" if $DEBUG; &search_cite ($texfile); &search_bibliography ($texfile); } ## Suchpfad aus $BIBINPUTS setzen @searchpath = split /:/, $BIBINPUTS; ## In jedem Verzeichnis aus $BIBINPUTS foreach $dir (@searchpath) { opendir (THISDIR, $dir); ## extrahiere alle *.bib Dateien @allbibfiles = grep /.*\.bib/, map "$dir/$_", readdir THISDIR; ## und suche diejenigen heraus, auf die im ## vorliegenden Dokument Bezug genommen wird. foreach $file (@bibliographylist) { @bibfiles = (@bibfiles, grep /${file}\.bib$/, @allbibfiles); } ## end (foreach) closedir (THISDIR); } ## end (foreach) ## Debugging: print "\nBibfiles: @bibfiles\n" if $DEBUG; ## Neuen Bibfile-Hash erstellen foreach $bibfile (@bibfiles) { &make_bibfile_hash ($bibfile); } # Statusausgabe print "\n\n$index entries of bibliography found in all LaTeX-files.\n"; print "Can assign them $index2 entries "; print "of bibliography found in all the BibTeX-files.\n"; if ( $index2 > $index ) { print "\nMaybe there are double entries in the BibTeX-files!\n"; print "So I'll only put $index entries of bibliography into"; print "$newbibfile!\n"; } ## end (if) ## Neues Bibfile ausgeben &make_new_bibfile; ## Statusmeldung print "\nDone.\n"; ########################################## ## Unterprogramme ## ########################################## sub make_bibfile_hash { ## Statusausgabe print ".."; local($bibfile) = @_; local($cite); open (BIBFILE, $bibfile) || die ("Kann $bibfile nicht lesen!\n"); LINE: while (<BIBFILE>) { if (/\@\w+\s*\{\s*(\S*)\s*,\s*/) ## @MasterThesis, @Book ... { ## gefunden! CITE: foreach $cite (@citelist) ## Durchlaufe alle Lit.- { ## Verweise und schaue, ob next CITE if ($cite ne $1); ## die gesuchte dabei ist. $newcitelist{$cite} = $_; ## Gesuchter Literaturverweis $index2++; ## vorhanden! Speichere ihn ## erhoehe Index2. while (<BIBFILE>) ## Fuege alle weiteren Zeilen { ## bis zur naechsten Typangabe if (/\@/) ## (bspw. @Book, ...) hinzu { ## Debugging print "\nCite_elem: $newcitelist{$cite}\n" if $DEBUG; redo LINE; ## und gehe zurueck. } else { s/%.*//; ## Sonst entferne Kommentare s/^\s*\n$//; ## und Leerzeichen und ## fuege aktuelle Zeile an. $newcitelist{$cite} .= $_; } ## end (if) } ## end (while) } ## end (foreach) } ## end (if) } ## end (while) close (BIBFILE); } ## end (sub make_bibfile_hash) sub search_cite { ## Statusausgabe print ".."; local($texfile) = @_; open (TEXFILE, $texfile) || die ("Can't read $texfile!\n"); LINE: while (<TEXFILE>) { while (m/\\cite\{(\S*)\}/g) ## Suche nach \cite{(...)} { @tempcitelist = (split /,/, $1); ## Erzeuge Referenzliste foreach $tempcite (@tempcitelist) ## Fuer jede Referenz { ## in der Referenzliste: foreach $cite (@citelist) ## Durchlaufe jedes { ## Listenelement, next LINE if ($cite eq $tempcite); ## ueberpruefe, ob } ## Listeneintrag $tempcite ## end (foreach) ## schon in der Liste ## @citelist vorhanden ist @citelist = (@citelist, $tempcite); ## Wenn nicht, dann $index++; ## erhoehe Index und } ## nehme $tempcite in ## end (foreach) ## @citelist auf. } ## end (if) } ## end (while) close (TEXFILE); ## Debugging print "Citelist: @citelist\n\n" if $DEBUG; } ## end (sub search_cite) sub make_new_bibfile { ## Abfrage, wenn main.bib schon vorhanden print "\n$newbibfile still exists. Continue (y/n)? " and &yes_no if -e "$newbibfile"; ## Leerzeile print "\n"; ## Ueberschreiben? Ja, dann lege ein neues File an. open (NEWBIBLIST, ">$newbibfile"); close (NEWBIBLIST); ## Setze $index zurueck $index = 0; ## Statusausgabe print "Following entries will be added:\n"; print "--------------------------------\n"; ## Sortierte Ausgabe aller BibTeX-Eintraege ## Fuer jeden Wert im Hash %newcitelist foreach $newcite (sort keys(%newcitelist)) { ## Erhoehe index $index++; ## Statusausgabe printf "%4d) %s\n", $index, $newcite; ## Neue main.bib Datei erstellen open (NEWBIBLIST, ">>$newbibfile"); print NEWBIBLIST ("$newcitelist{$newcite}\n"); close (NEWBIBLIST); } } ## end (sub make_new_bibfile) sub search_bibliography { ## Statusausgabe print ".."; local($texfile) = @_; open (TEXFILE, $texfile) || die ("Kann $texfile nicht lesen!\n"); LINE: while (<TEXFILE>) { if (/\\bibliography\{([\w\s,]*)\}/g) ## Suche nach { ## \bibliography{(...)} ## Gefundenen String splitten und ## der Bibliographieliste anhaengen. @bibliographylist = (@bibliographylist, split /,/, $1); ## Debugging print "\nBibliographylist: @bibliographylist\n" if $DEBUG; } ## end (if) } ## end (while) close (TEXFILE); } ## end (sub search_bibliography) ## Abfrage nach Ja oder Nein sub yes_no { ## Akzepiere eingegebene Zeichenkette nur, ## wenn 'Y' oder 'y' eingegeben wurde. $ans = <stdin>; return if $ans =~ /^[Yy]$/; ## Falsche Taste erwischt oder Unsinn eingegeben? if ($ans !~ /^[Nn]$/) { print "Please type Y,y or N,n! (y,n)? " and &yes_no; } else { ## Statusausgabe print "\nQuit!\n"; exit 1; } ## end (if) } ## end (sub yes_no) ## Eingabe Fehler sub usage { print <<EOF; This is Makebib Version $MakebibVERSION by Peter Allgeyer, Institut fuer Informatik, Technical University of Munich. Usage: makebib.pl [-newbibfile <file>] [-debug] [-h(elp)] EOF } ## end (sub usage)