在 python 中使用正则表达式从 tex 文件中提取引用的 bibtex 键
Extract cited bibtex keys from tex file using regex in python
我正在尝试使用 python 中的正则表达式从 LaTeX 文档中提取引用的 BibTeX 键。
如果引文被注释掉(前面有 %),我想将其排除,但如果前面有百分号 (\%),我仍将其包括在内。
这是我到目前为止的想法:
\(?:no|)cite\w*\{(.*?)\}
试用示例:
blablabla
Author et. al \cite{author92} bla bla. % should match
\citep{author93} % should match
\nocite{author94} % should match
100\%\nocite{author95} % should match
100\% \nocite{author95} % should match
%\nocite{author96} % should not match
\cite{author97, author98, author99} % should match
\nocite{*} % should not match
Regex101 测试:https://regex101.com/r/ZaI8kG/2/
感谢任何帮助。
使用较新的 regex
模块 (pip install regex
),表达式如下:
(?<!\)%.+(*SKIP)(*FAIL)|\(?:no)?citep?\{(?P<author>(?!\*)[^{}]+)\}
更详细:
(?<!\)%.+(*SKIP)(*FAIL) # % (not preceded by \)
# and the whole line shall fail
| # or
\(?:no)?citep? # \nocite, \cite or \citep
\{ # { literally
(?P<author>(?!\*)[^{}]+) # must not start with a star
\} # } literally
如果安装另一个库不是一个选项,则需要将表达式更改为
(?<!\)%.+
|
(\(?:no)?citep?
\{
((?!\*)[^{}]+)
\})
并且需要以编程方式检查第二个捕获组是否已设置(即不为空)。
后者可能在 Python
:
import re
latex = r"""
blablabla
Author et. al \cite{author92} bla bla. % should match
\citep{author93} % should match
\nocite{author94} % should match
100\%\nocite{author95} % should match
100\% \nocite{author95} % should match
%\nocite{author96} % should not match
\cite{author97, author98, author99} % should match
\nocite{*} % should not match
"""
rx = re.compile(r'''(?<!\)%.+|(\(?:no)?citep?\{((?!\*)[^{}]+)\})''')
authors = [m.group(2) for m in rx.finditer(latex) if m.group(2)]
print(authors)
产生
['author92', 'author93', 'author94', 'author95', 'author95', 'author97, author98, author99']
我没有遵循最后一个逻辑,在我看来 *
在 {}
中可能不需要,在那种情况下,也许您想设计一个表达式类似于:
^(?!(%\(?:no)?cite\w*\{([^}]*?)\}))[^*\n]*$
虽然不确定。
DEMO
我正在尝试使用 python 中的正则表达式从 LaTeX 文档中提取引用的 BibTeX 键。
如果引文被注释掉(前面有 %),我想将其排除,但如果前面有百分号 (\%),我仍将其包括在内。
这是我到目前为止的想法:
\(?:no|)cite\w*\{(.*?)\}
试用示例:
blablabla
Author et. al \cite{author92} bla bla. % should match
\citep{author93} % should match
\nocite{author94} % should match
100\%\nocite{author95} % should match
100\% \nocite{author95} % should match
%\nocite{author96} % should not match
\cite{author97, author98, author99} % should match
\nocite{*} % should not match
Regex101 测试:https://regex101.com/r/ZaI8kG/2/
感谢任何帮助。
使用较新的 regex
模块 (pip install regex
),表达式如下:
(?<!\)%.+(*SKIP)(*FAIL)|\(?:no)?citep?\{(?P<author>(?!\*)[^{}]+)\}
更详细:
(?<!\)%.+(*SKIP)(*FAIL) # % (not preceded by \)
# and the whole line shall fail
| # or
\(?:no)?citep? # \nocite, \cite or \citep
\{ # { literally
(?P<author>(?!\*)[^{}]+) # must not start with a star
\} # } literally
如果安装另一个库不是一个选项,则需要将表达式更改为
(?<!\)%.+
|
(\(?:no)?citep?
\{
((?!\*)[^{}]+)
\})
并且需要以编程方式检查第二个捕获组是否已设置(即不为空)。
后者可能在 Python
:
import re
latex = r"""
blablabla
Author et. al \cite{author92} bla bla. % should match
\citep{author93} % should match
\nocite{author94} % should match
100\%\nocite{author95} % should match
100\% \nocite{author95} % should match
%\nocite{author96} % should not match
\cite{author97, author98, author99} % should match
\nocite{*} % should not match
"""
rx = re.compile(r'''(?<!\)%.+|(\(?:no)?citep?\{((?!\*)[^{}]+)\})''')
authors = [m.group(2) for m in rx.finditer(latex) if m.group(2)]
print(authors)
产生
['author92', 'author93', 'author94', 'author95', 'author95', 'author97, author98, author99']
我没有遵循最后一个逻辑,在我看来 *
在 {}
中可能不需要,在那种情况下,也许您想设计一个表达式类似于:
^(?!(%\(?:no)?cite\w*\{([^}]*?)\}))[^*\n]*$
虽然不确定。