はじめに
BibTeX ファイルには、論文のメタデータが含まれていますが、自動生成された BibTeX ファイルにはしばしばウムラウト(ä, ö, ü)やアクセント付き文字(é, è, ñ など)がそのまま含まれており、LaTeX で適切に処理されないことがあります。
この記事では、BibTeX
の特殊文字を Python
の bibtexparser
で LaTeX
形式に変換する例について紹介します。
例えば、次のような BibTeX エントリがあったとします。
@ARTICLE{Holzer1997-cr,
author = "Hölzer, G and Fritsch, M",
title = "Kα and Kβ x-ray emission lines",
journal = "Phys. Rev. A",
year = 1997
}
このままでは Hölzer
という名前が正しく表示されません。正しい LaTeX 形式では次のように書くべきです。
author = "H{"o}lzer, G and Fritsch, M"
この変換を手作業で行うのは面倒です。そこで、Python を使って特殊文字を自動変換するスクリプトを作成します。
必要なライブラリ
このスクリプトには bibtexparser
を使用します。
pip install bibtexparser
実行方法
-
input.bib
に変換したい BibTeX ファイルを保存。 - 上記
rk_paper_util_bibtexparser.py input.bib
スクリプトを実行。python rk_paper_util_bibtexparser.py input.bib
-
input_cvt.bib
に変換後のデータが保存される。
変換の確認
元の input.bib
:
@ARTICLE{Holzer1997-cr,
author = "Hölzer, G and Fritsch, M",
title = "Kα and Kβ x-ray emission lines",
journal = "Phys. Rev. A",
year = 1997
}
変換後の input_cvt.bib
:
@ARTICLE{Holzer1997-cr,
author = "H{"o}lzer, G and Fritsch, M",
title = "Kα and Kβ x-ray emission lines",
journal = "Phys. Rev. A",
year = 1997
}
このように、他のテキストに影響を与えることなく、ウムラウトの部分だけ tex 表記になると思います。
Python スクリプトの解説
以下の Python スクリプトを実行することで、BibTeX ファイルの特殊文字を適切な LaTeX 形式に変換できます。
下記の github にもコードを置いています。
#!/usr/bin/env python
import argparse
import bibtexparser
import re
import os
# 特殊文字をLaTeXのエスケープ表現に変換するためのマッピング
TEX_REPLACEMENTS = {
"ä": r"{\"a}", "ö": r"{\"o}", "ü": r"{\"u}", "ß": r"{\ss}",
"Ä": r"{\"A}", "Ö": r"{\"O}", "Ü": r"{\"U}",
"é": r"{\'e}", "è": r"{\`e}", "ê": r"{\^e}", "ë": r"{\"e}",
"É": r"{\'E}", "È": r"{\`E}", "Ê": r"{\^E}", "Ë": r"{\"E}",
"á": r"{\'a}", "à": r"{\`a}", "â": r"{\^a}", "ã": r"{\~a}",
"Á": r"{\'A}", "À": r"{\`A}", "Â": r"{\^A}", "Ã": r"{\~A}",
"í": r"{\'i}", "ì": r"{\`i}", "î": r"{\^i}", "ï": r"{\"i}",
"Í": r"{\'I}", "Ì": r"{\`I}", "Î": r"{\^I}", "Ï": r"{\"I}",
"ó": r"{\'o}", "ò": r"{\`o}", "ô": r"{\^o}", "õ": r"{\~o}",
"Ó": r"{\'O}", "Ò": r"{\`O}", "Ô": r"{\^O}", "Õ": r"{\~O}",
"ú": r"{\'u}", "ù": r"{\`u}", "û": r"{\^u}",
"Ú": r"{\'U}", "Ù": r"{\`U}", "Û": r"{\^U}",
"ñ": r"{\~n}", "Ñ": r"{\~N}", "ç": r"{\c c}", "Ç": r"{\c C}",
"ń": r"{\'n}", "Ň": r"{\v{N}}", "ň": r"{\v{n}}",
"š": r"{\v{s}}", "Š": r"{\v{S}}",
"ž": r"{\v{z}}", "Ž": r"{\v{Z}}",
"ř": r"{\v{r}}", "Ř": r"{\v{R}}",
"č": r"{\v{c}}", "Č": r"{\v{C}}",
"ě": r"{\v{e}}", "Ě": r"{\v{E}}"
}
def texify(text):
"""文字列内の特殊文字をLaTeX形式に変換する関数"""
return re.sub(
'|'.join(map(re.escape, TEX_REPLACEMENTS.keys())), # 変換対象の文字を正規表現でマッチさせる
lambda match: TEX_REPLACEMENTS[match.group(0)], # マッチした文字をLaTeX表現に変換
text
)
def process_bibtex(input_file, output_file):
"""BibTeXファイルを読み込み、特殊文字をLaTeX形式に変換して保存する関数"""
with open(input_file, encoding="utf-8") as bib_file:
bib_database = bibtexparser.load(bib_file) # BibTeXファイルを読み込む
# 各エントリのすべてのフィールドを変換
for entry in bib_database.entries:
for key, value in entry.items():
entry[key] = texify(value) # LaTeX形式に変換
# 変換後のデータを新しいBibTeXファイルとして保存
with open(output_file, "w", encoding="utf-8") as bib_file:
bibtexparser.dump(bib_database, bib_file)
print(f"変換完了: {output_file}") # 完了メッセージを表示
def main():
"""コマンドライン引数を処理し、BibTeXファイルを変換するメイン関数"""
parser = argparse.ArgumentParser(
description="BibTeXファイル内の特殊文字をLaTeX形式に変換するツール"
)
parser.add_argument("input", help="入力するBibTeXファイルのパス")
parser.add_argument("--output", help="出力ファイルのパス(省略時は自動生成)")
args = parser.parse_args()
# 出力ファイル名を決定(指定がない場合は元のファイル名に "_cvt" を付ける)
if args.output:
output_file = args.output
else:
base, ext = os.path.splitext(args.input)
output_file = f"{base}_cvt{ext}"
process_bibtex(args.input, output_file) # BibTeXファイルを変換
if __name__ == "__main__":
main() # メイン関数を実行
詳しい説明:
-
re.sub(pattern, replacement, text)
のreplacement
に関数を指定すると、検索結果ごとにその関数が呼ばれる。- これは、通常
replacement
には固定の文字列を指定することが多いですが、関数を指定すると、re.sub()
はマッチした部分ごとにその関数を呼び出します。
- これは、通常
-
関数が呼ばれる際、
re.Match
オブジェクトがreplacement
で指定した関数に渡される。- ここで渡される
re.Match
オブジェクトには、マッチした文字列に関する情報が格納されています。 -
.group(0)
を呼び出すと、マッチした文字列全体が取得できます。
- ここで渡される
-
したがって、
lambda match: TEX_REPLACEMENTS[match.group(0)]
のmatch
には、re.Match
オブジェクトが渡されることになる。-
match.group(0)
を使うことで、マッチした文字列を取得し、それをTEX_REPLACEMENTS
辞書で LaTeX 形式の文字列に変換する。
-
具体的な動作を確認
次のコードで re.sub()
の replacement
に関数を指定した場合の動作を確認できます。
import re
# 変換マッピング
TEX_REPLACEMENTS = {
"ä": r"{\"a}", "ö": r"{\"o}", "ü": r"{\"u}", "ß": r"{\ss}",
"Ä": r"{\"A}", "Ö": r"{\"O}", "Ü": r"{\"U}"
}
def replacement_function(match):
print(f"マッチした文字列: {match.group(0)}") # どの文字がマッチしているか確認
return TEX_REPLACEMENTS[match.group(0)] # LaTeX 形式に変換
text = "Hölzer, Müller, Weiß"
converted_text = re.sub('|'.join(map(re.escape, TEX_REPLACEMENTS.keys())), replacement_function, text)
print(f"変換後のテキスト: {converted_text}")
実行結果
マッチした文字列: ö
マッチした文字列: ü
マッチした文字列: ß
変換後のテキスト: H{\"o}lzer, M{\"u}ller, W{\ss}
re.sub()
の詳細解説
この関数 re.sub()
は、text
内の特定の文字を置換するために使用されています。
-
re.escape(TEX_REPLACEMENTS.keys())
:-
TEX_REPLACEMENTS
のキー(特殊文字)を正規表現で安全に扱えるようエスケープします。 - 例えば
ä
などの特殊文字が正規表現のメタ文字と衝突しないよう処理されます。
-
-
'|'.join(map(re.escape, TEX_REPLACEMENTS.keys()))
:-
TEX_REPLACEMENTS.keys()
はä
,ö
,ü
などの特殊文字のリストです。 - それぞれを
re.escape()
でエスケープし、|
(OR 演算)でつなげて一つの正規表現パターンにします。 - 例えば、
ä|ö|ü|ß
のようなパターンが生成されます。
-
-
lambda match: TEX_REPLACEMENTS[match.group(0)]
:-
match.group(0)
はre.sub()
によって見つかった一致部分を取得します。 - 例えば、
ö
に一致した場合、match.group(0)
はö
になります。 - その値を
TEX_REPLACEMENTS
の辞書から取得し、対応する LaTeX 形式に変換します。 - 例えば、
match.group(0) = "ö"
のとき、TEX_REPLACEMENTS["ö"]
は{"o}
となり、これに置換されます。
-
具体例:
text = "Hölzer, Müller, naïve"
converted_text = texify(text)
print(converted_text)
出力:
H{"o}lzer, M{"u}ller, na{"i}ve
このように、re.sub()
を用いることで、文字列の中に含まれる特殊文字を LaTeX 形式に適切に変換できます。
まとめ
- BibTeX の特殊文字を LaTeX 形式に自動変換する Python スクリプトを作成した。
-
bibtexparser
を使って BibTeX をパースし、ウムラウトやアクセント記号を{"o}
のように変換。 -
re.sub()
とmatch.group(0)
を活用し、正規表現を用いた効率的な変換を実現。 -
group(0)
の意味とgroup(1)
,group(2)
との違いを具体例を用いて解説しました。
これを活用し、手作業のミスを防ぎ、LaTeX でのフォーマットエラーを回避して、より正確な BibTeX ファイルを簡単に作成してみましょう。
(補足) bibtexparser
と pybtex
の違い
Python で BibTeX を処理するライブラリには bibtexparser
のほかに pybtex
もあります。それぞれの違いを理解して適切に使い分けることが重要です。
ライブラリ | 特徴 |
---|---|
bibtexparser |
BibTeX を Python の辞書形式で扱うシンプルなライブラリ。データの編集や JSON との変換が容易。 |
pybtex |
BibTeX の解析に加え、LaTeX スタイルのフォーマットや出力をサポート。書誌情報の整形などに適している。 |
bibtexparser
はデータの読み込みや編集に向いているのに対し、pybtex
は LaTeX での書誌情報のレンダリングに特化しているため、用途に応じて選択すると良いでしょう。