Zitatautoren mehrerer Publikationen in LaTeX
LaTeXPythonHier ist ein Code-Ausschnitt aus meinem LaTeX-Dokument meiner Doktorarbeit.
Ziel ist es, \citeauthor{} zu verwenden, aber mit mehreren Publikationen. Das unterstützt \citeauthor{} nicht.
Außerdem sollen Autoren, die an mehreren Publikationen beteiligt sind, nicht mehrfach erscheinen.
Um das zu erreichen, habe ich einen benutzerdefinierten Befehl geschrieben: \citeauthors. Dieser nimmt eine Liste von Zitationsschlüsseln entgegen, extrahiert die eindeutigen Autoren und formatiert sie lesbar.
Dies ist die Implementierung des \citeauthors Kommandos (erfordert python und lualatex):
% Create a new citation command that calls a Python script to get deduplicated authors
\usepackage{luacode}
\begin{luacode*}
function citeauthors(keys)
local pycmd = string.format('python3 citeauthors.py "%s" 2>/dev/null', keys)
local handle = io.popen(pycmd)
local result = handle:read("*a")
local status = handle:close()
-- Strip trailing whitespace and newlines
result = result:gsub("^%s+", ""):gsub("%s+$", "")
-- Only print if result is not empty and command succeeded
if result ~= "" then
-- Use catcode -1 to print verbatim (no special char interpretation)
tex.print(-1, result)
end
end
\end{luacode*}
\newcommand{\citeauthors}[1]{%
\directlua{citeauthors("\luaescapestring{#1}")}%
}
Und das entsprechende citeauthors.py Skript, das die Zitationsschlüssel verarbeitet und eindeutige Autoren extrahiert:
#!/usr/bin/env python
import contextlib
import hashlib
import io
import os
import pickle
import sys
import bibtexparser
from bibtexparser.bparser import BibTexParser
from bibtexparser.customization import author as parse_authors
def get_cache_path(bibfile):
"""Generate cache file path based on bibfile path and modification time."""
cache_dir = os.path.join(os.path.dirname(bibfile), ".cache")
os.makedirs(cache_dir, exist_ok=True)
# Create a unique cache filename based on bibfile path and mtime
mtime = os.path.getmtime(bibfile)
cache_key = f"{bibfile}_{mtime}".encode("utf-8")
cache_hash = hashlib.md5(cache_key).hexdigest()
return os.path.join(cache_dir, f"bibcache_{cache_hash}.pkl")
def load_bib_database(bibfile):
"""Load bibliography database with caching."""
cache_path = get_cache_path(bibfile)
# Try to load from cache
if os.path.exists(cache_path):
try:
with open(cache_path, "rb") as f:
return pickle.load(f)
except (pickle.PickleError, EOFError):
pass # Cache corrupted, will regenerate
# Parse the bibfile
with contextlib.redirect_stderr(io.StringIO()):
with open(bibfile, encoding="utf-8") as bibtex_file:
parser = BibTexParser(common_strings=True)
parser.ignore_nonstandard_types = True
parser.customization = parse_authors
bib_database = bibtexparser.load(bibtex_file, parser=parser)
# Save to cache
try:
with open(cache_path, "wb") as f:
pickle.dump(bib_database, f)
except (IOError, pickle.PickleError):
pass # Failed to cache, but continue
return bib_database
def get_authors(keys, bibfile):
"""Extract author last names from bibliography entries."""
bib_database = load_bib_database(bibfile)
seen = set()
lastnames = []
for key in keys:
entry = next((e for e in bib_database.entries if e.get("ID") == key), None)
if entry and "author" in entry:
for a in entry["author"]:
# Extract last name (assume format: 'Lastname, Firstname' or 'Firstname Lastname')
if "," in a:
lastname = a.split(",")[0].strip()
else:
lastname = a.split()[-1].strip()
if lastname not in seen:
lastnames.append(lastname)
seen.add(lastname)
return lastnames
def format_authors(authors):
n = len(authors)
if n == 0:
return ""
elif n == 1:
return authors[0]
elif n == 2:
return f"{authors[0]} and {authors[1]}"
else:
return f"{', '.join(authors[:-1])}, and {authors[-1]}"
if __name__ == "__main__":
if len(sys.argv) < 2:
print("")
sys.exit(0)
keys = [k.strip() for k in sys.argv[1].split(",") if k.strip()]
bibfile = os.path.join(os.path.dirname(__file__), "references.bib") # Hier muss der Pfad zu deiner .bib Datei angepasst werden
authors = get_authors(keys, bibfile)
print(format_authors(authors))
Beachte, dass das citeauthors.py Skript eine references.bib Datei im selben Verzeichnis erwartet, die die Bibliographieeinträge enthalten sollte.
Das Skript verwendet Caching, um wiederholte Aufrufe mit derselben Bibliographiedatei zu beschleunigen.
Das Paket bibtexparser ist erforderlich, um die .bib Datei zu parsen, die über PIP installiert werden kann (pip install bibtexparser).
