選択したエントリをbibtexファイルから抽出するスクリプト


11

各エントリが一般的な構造を持つ多くのエントリを持つ大きなbibtexファイルがあります

@ARTICLE{AuthorYear,
item = {...},
item = {...},
item = {...},
etc
}

ARTICLE例によっては別の単語になる場合がありますBOOK

私がやりたいのは、与えられたAuthorYearでエントリを抽出して新しい.bibファイルに入れる簡単なスクリプト(できればシェルスクリプト)を書くことです。

AuthorYearによるエントリの最初の文と最後の1回のクローズ}で認識でき、おそらくsedエントリの抽出に使用できると想像できますが、正確にこれを行う方法がわかりません。誰かが私にこれをどのように達成するかを教えてもらえますか?

それはおそらく次のようなものでなければなりません

sed -n "/AuthorYear/,/\}/p" file.bib

しかし}、エントリの最初の項目が閉じているため、この出力は停止します。

@ARTICLE{AuthorYear,
item = {...},

したがって、これが}行の唯一の文字であるかどうかを認識し、これが当てはまる場合にのみ「sed」で読み取りを停止する必要があります。


私はあなたのコードを少しだけ修正することができました:sed -n "/AuthorYear/,/\}$/p"$記号に注意してください。}ビビテムの結末を出力しないことを除いて、それはうまく働きます。ところで、の使用はsed必要ですか?
Barun

@Barunの使用sedはまったく必要ありません。それが最も簡単なオプションだと思いました。私は少し異なるコードを見つけました。sed -n "/AuthorYear/, /^ *\}/p"それは}、スペースがある場合は閉じたりスペースを修正したりすることを含め、私が望んでいるとおりに機能するようです
Michiel

回答:


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,

個人的には、フィルタリングロジックが複雑になったときにスクリプト言語に移行することを好みます。それはおそらく、少なくとも読みやすさの要素に利点があります。


注意してください{}。ネストされたを持つエントリはたくさんあります。エントリがで終わることを確認できる場合\n}、停止することができます^}
フォンブランド

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;
}

おそらくモジュールをインストールする必要があります: cpan install BibTeX::Parser


1

これで、PythonでBibTeXデータベースを分析できるようにするPython bibparsingモジュールも用意されました。たとえば、次のスクリプトを使用して、共同論文の著者数を計算します。

#!/usr/bin/python
import sys
import bibtexparser as bp
with open(sys.argv[1]) as bibtex_file:
    bd = bp.load(bibtex_file)
    for art in bd.entries_dict:
    print("*********")
    ae = bd.entries_dict[art]
    print(ae[u'title'])
    auths=ae[u'author'].split(" and ")
    print(len(auths))
    print(auths[0]+" --- "+auths[-1])

1

別のオプションは、bibtoolを使用することです。

例:

bibtool -- select{$key AuthorYear”} input.bib -o output.bib

特定のケースについては、マニュアルを確認してください。


0

これは、各行を読み取り、正規表現マッチングを使用して、先頭に必要なパターンを持つ各エントリを抽出するBashスクリプトです。あなたはそれgetbibsか何かを呼び出すことができます:

#!/usr/bin/env bash
# usage: ./getbibs pattern input.bib output.bib

while read entry; do
    if [[ $entry =~ ^@.*{$1,$ ]]; then
        printf "%s\n" "$entry" >> "$3"
        while read item; do
            [[ $item =~ ^@.*$ ]] && break
            printf "%s\n" "$item" >> "$3"
        done
    fi
done < "$2"

著者年が1989年のすべてのエントリを抽出するには、次のようにします。

$ chmod +x ./getbibs
$ ./getbibs 1989 file.bib author.bib

まだテストしていない問題があるかもしれませんが、問題なく動作するようです。


0

完全を期すために、私が自分で考え出した方法は、他のいくつかの方法ほどではありませんが、うまくいきます。

entries=( AuthorYear1 AuthorYear2 )
for entry in "${entries[@]}" do
     sed -n "/"${entry}"/, /^ *\}/p" refs.bib 
done

コマンドラインから実行するか、bashスクリプトに入れることができます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.