从 bibtex 文件中提取选定条目的脚本

Mic*_*iel 11 sed shell-script text-processing

我有一个包含许多条目的大型 bibtex 文件,其中每个条目都有一般结构

@ARTICLE{AuthorYear,
item = {...},
item = {...},
item = {...},
etc
}
Run Code Online (Sandbox Code Playgroud)

(在某些情况下ARTICLE可能是不同的词,例如BOOK

我想要做的是编写一个简单的脚本(最好只是一个 shell 脚本)来提取给定 AuthorYear 的条目并将它们放入一个新的 .bib 文件中。

我可以想象,我可以通过 AuthorYear 识别条目的第一句话,通过单个结束识别最后一句,}并且可能用于sed提取条目,但我真的不知道如何准确地做到这一点。有人能告诉我我将如何实现这一目标吗?

它可能应该是这样的

sed -n "/AuthorYear/,/\}/p" file.bib
Run Code Online (Sandbox Code Playgroud)

但是由于}条目的第一项中的关闭而停止,因此给出了以下输出:

@ARTICLE{AuthorYear,
item = {...},
Run Code Online (Sandbox Code Playgroud)

所以我需要识别是否}是一行中唯一的字符,并且只有在这种情况下 'sed' 停止阅读。

gle*_*man 8

我建议使用一种经过实战测试的 BibTeX 库的语言,而不是重新发明那个轮子。例如

#!/usr/bin/env perl
use strict;
use warnings;
use autodie;
use BibTeX::Parser;

open my $fh, '<', $ARGV[0];
my $parser = BibTeX::Parser->new($fh);
my @authoryear;
while (my $entry = $parser->next) {
    if ($entry->parse_ok) {
        if ($entry->key eq "AuthorYear") {
            push @authoryear, $entry;
        }
    }
    else {
        warn "Error parsing file: " . $entry->error;
    }
}

# I'm not familiar with bibtex files, so this may be insufficient
open my $out, '>', "authoryear.bib";
foreach my $entry (@authoryear) {
    say $out $entry->raw_bibtex;
}
Run Code Online (Sandbox Code Playgroud)

您可能必须安装该模块: cpan install BibTeX::Parser


Bar*_*run 2

以下 Python 脚本执行所需的过滤。

#!/usr/bin/python
import re

# Bibliography entries to retrieve
# Multiple pattern compilation from: http://stackoverflow.com/a/11693340/147021
pattern_strings = ['Author2010', 'Author2012',]
pattern_string = '|'.join(pattern_strings)
patterns = re.compile(pattern_string)


with open('bibliography.bib', 'r') as bib_file:
    keep_printing = False
    for line in bib_file:
        if patterns.findall(line):
            # Beginning of an entry
            keep_printing = True

        if line.strip() == '}':
            if keep_printing:
                print line
                # End of an entry -- should be the one which began earlier
                keep_printing = False

        if keep_printing:
            # The intermediate lines
            print line,
Run Code Online (Sandbox Code Playgroud)

就我个人而言,当过滤逻辑变得复杂时,我更喜欢转向脚本语言。这也许至少在可读性方面有优势。