regex 用Python解析BibTeX引文格式

4ngedf3f  于 2023-02-25  发布在  Python
关注(0)|答案(5)|浏览(132)

在python中解析这些结果的最好方法是什么?我试过正则表达式,但是不能让它工作。我正在寻找一个标题,作者等作为关键字的字典。

@article{perry2000epidemiological,
  title={An epidemiological study to establish the prevalence of urinary symptoms and felt need in the community: the Leicestershire MRC Incontinence Study},
  author={Perry, Sarah and Shaw, Christine and Assassa, Philip and Dallosso, Helen and Williams, Kate and Brittain, Katherine R and Mensah, Fiona and Smith, Nigel and Clarke, Michael and Jagger, Carol and others},
  journal={Journal of public health},
  volume={22},
  number={3},
  pages={427--434},
  year={2000},
  publisher={Oxford University Press}
}
kgqe7b3p

kgqe7b3p1#

这看起来像一个引文格式,你可以这样解析它:

>>> import re

>>> kv = re.compile(r'\b(?P<key>\w+)={(?P<value>[^}]+)}')

>>> citation = """
... @article{perry2000epidemiological,
...   title={An epidemiological study to establish the prevalence of urinary symptoms and felt need in the community: the Leicestershire MRC Incontinence
...  Study},
...   author={Perry, Sarah and Shaw, Christine and Assassa, Philip and Dallosso, Helen and Williams, Kate and Brittain, Katherine R and Mensah, Fiona and
...  Smith, Nigel and Clarke, Michael and Jagger, Carol and others},
...   journal={Journal of public health},
...   volume={22},
...   number={3},
...   pages={427--434},
...   year={2000},
...   publisher={Oxford University Press}
... }
... """

>>> dict(kv.findall(citation))
{'author': 'Perry, Sarah and Shaw, Christine and Assassa, Philip and Dallosso, Helen and Williams, Kate and Brittain, Katherine R and Mensah, Fiona and Smith, Nigel and Clarke, Michael and Jagger, Carol and others',
 'journal': 'Journal of public health',
 'number': '3',
 'pages': '427--434',
 'publisher': 'Oxford University Press',
 'title': 'An epidemiological study to establish the prevalence of urinary symptoms and felt need in the community: the Leicestershire MRC Incontinence Study',
 'volume': '22',
 'year': '2000'}

正则表达式使用两个命名的捕获组(主要是为了直观地表示什么是什么)。

  • “key”是任何1+ unicode单词字符,单词边界在左边,文字等号在右边;
  • “value”是两个花括号内的内容。只要你不希望有“嵌套”的花括号,你可以方便地使用[^}]。换句话说,值只是花括号内的一个或多个不是花括号的字符。
esyap4oy

esyap4oy2#

您可能正在寻找BibTeX解析器:https://bibtexparser.readthedocs.io/en/master/
图片来源:www.example.comhttps://bibtexparser.readthedocs.io/en/master/tutorial.html#step-0-vocabulary
输入/创建bibtex文件:

bibtex = """@ARTICLE{Cesar2013,
  author = {Jean César},
  title = {An amazing title},
  year = {2013},
  month = jan,
  volume = {12},
  pages = {12--23},
  journal = {Nice Journal},
  abstract = {This is an abstract. This line should be long enough to test
     multilines...},
  comments = {A comment},
  keywords = {keyword1, keyword2}
}
"""

with open('bibtex.bib', 'w') as bibfile:
    bibfile.write(bibtex)

解析它:

import bibtexparser

with open('bibtex.bib') as bibtex_file:
    bib_database = bibtexparser.load(bibtex_file)

print(bib_database.entries)

输出:

[{'journal': 'Nice Journal',
  'comments': 'A comment',
  'pages': '12--23',
  'month': 'jan',
  'abstract': 'This is an abstract. This line should be long enough to test\nmultilines...',
  'title': 'An amazing title',
  'year': '2013',
  'volume': '12',
  'ID': 'Cesar2013',
  'author': 'Jean César',
  'keyword': 'keyword1, keyword2',
  'ENTRYTYPE': 'article'}]
iq3niunx

iq3niunx3#

您可以使用regex:

import re

s = """
  @article{perry2000epidemiological,
  title={An epidemiological study to establish the prevalence of urinary symptoms and felt need in the community: the Leicestershire MRC Incontinence Study},
  author={Perry, Sarah and Shaw, Christine and Assassa, Philip and Dallosso, Helen and Williams, Kate and Brittain, Katherine R and Mensah, Fiona and Smith, Nigel and Clarke, Michael and Jagger, Carol and others},
  journal={Journal of public health},
  volume={22},
  number={3},
  pages={427--434},
  year={2000},
  publisher={Oxford University Press}
}
"""
results = re.findall('(?<=@article\{)[a-zA-Z0-9]+|(?<=\=\{)[a-zA-Z0-9:\s,]+|[a-zA-Z]+(?=\=)|@[a-zA-Z0-9]+', s)
final_results = {results[i][1:] if results[i].startswith('@') else results[i]:int(results[i+1]) if results[i+1].isdigit() else results[i+1] for i in range(0, len(results), 2)}

输出:

{'publisher': 'Oxford University Press', 'author': 'Perry, Sarah and Shaw, Christine and Assassa, Philip and Dallosso, Helen and Williams, Kate and Brittain, Katherine R and Mensah, Fiona and Smith, Nigel and Clarke, Michael and Jagger, Carol and others', 'journal': 'Journal of public health', 'title': 'An epidemiological study to establish the prevalence of urinary symptoms and felt need in the community: the Leicestershire MRC Incontinence Study', 'number': 3, 'volume': 22, 'year': 2000, 'article': 'perry2000epidemiological', 'pages': 427}
tv6aics1

tv6aics14#

您可能正在寻找re.split

import re
article_dict = {}
with open('inp.txt') as f:
    for line in f.readlines()[1:-1]:
        info = re.split(r'=',line.strip())
        article_dict[info[0]] = info[1]

我假设您需要去掉末尾的大括号和逗号,这只是一个简单的替换或切片任务。

{'title': '{An epidemiological study to establish the prevalence of urinary symptoms and felt need in the community: the Leicestershire MRC Incontinence Study},',
 'author': '{Perry, Sarah and Shaw, Christine and Assassa, Philip and Dallosso, Helen and Williams, Kate and Brittain, Katherine R and Mensah, Fiona and Smith, Nigel and Clarke, Michael and Jagger, Carol and others},', 
 'journal': '{Journal of public health},', 
 'volume': '{22},', 
 'number': '{3},', 
 'pages': '{427--434},', 
 'year': '{2000},', 
 'publisher': '{Oxford University Press}'}
00jrzges

00jrzges5#

由于我在使用其他解决方案时遇到了一些问题(而且我不想安装新的库),下面是我的尝试。
请注意,此方法假定所有参考书目记录的格式为:

@record_type{ record_id,
 key1 = {value1},
 key2 = {value2},
 key3 = ...
}

除了month字段外,所有字段通常都是这种情况,因为该字段经常缺少大括号,我为它添加了一个特殊的大小写。

import re
# load bib file
with open('bib.bib','r') as bibfile:
    content = bibfile.read() 

bib_lookup = {}
# split at @
for s in content.split("@"):
    # Note: add other record types if necessary
    for match_word in ['article','techreport','misc','book']:
        if match_word in s:
            # get record id from first line after "@" ending with ","
            article_id = re.findall(match_word+'\{(.*?),', s)
            if article_id:
                # fix month formatting 
                if "month" in s:
                    m = re.findall(',\n  month = (.*?),', s)
                    # replace only when curly braces are missing around month
                    if m:                          
                        s = s.replace(f"month = {m[0]},",f"month = {{{m[0]}}},")                

                # regex for keys
                results1 = [r.strip() for r in re.findall(',\n  (.*?)=', s)]
                # regex for values
                results2 = [r.strip() for r in re.findall('\{(.*?)\},', s)]
                res = dict(zip(results1,results2))            
                bib_lookup[article_id[0]] = res
            else:
                print("Warning: unable to parse record")
                print(s)

相关问题