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' 停止阅读。
我建议使用一种经过实战测试的 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
以下 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)
就我个人而言,当过滤逻辑变得复杂时,我更喜欢转向脚本语言。这也许至少在可读性方面有优势。