Skript zum Extrahieren ausgewählter Einträge aus einer Bibtex-Datei

11

Ich habe eine große Bibtex-Datei mit vielen Einträgen, wobei jeder Eintrag die allgemeine Struktur hat

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

(in einigen Fällen ARTICLEkönnte ein anderes Wort zB sein BOOK)

Was ich tun möchte, ist ein einfaches Skript (vorzugsweise nur ein Shell-Skript) zu schreiben, um Einträge mit einem bestimmten AuthorYear zu extrahieren und diese in eine neue BIB-Datei einzufügen.

Ich kann mir vorstellen, dass ich den ersten Satz eines Eintrags von AuthorYear und den letzten am einzelnen Abschluss erkennen }und möglicherweise sedzum Extrahieren des Eintrags verwenden kann, aber ich weiß nicht genau, wie ich das genau machen soll. Kann mir jemand sagen, wie ich das erreichen würde?

Es sollte wahrscheinlich so etwas sein

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

Dies hört jedoch aufgrund des Schließens }im ersten Element des Eintrags auf, wodurch diese Ausgabe erfolgt:

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

Ich muss also erkennen, ob das }das einzige Zeichen in einer Zeile ist, und nur dann "sed" aufhören zu lesen, wenn dies der Fall ist.

Michiel
quelle
Ich konnte Ihren Code nur ein wenig ändern : sed -n "/AuthorYear/,/\}$/p". Beachten Sie das $Symbol. Es funktioniert }einwandfrei , außer dass das Schließen eines Bibitems nicht gedruckt wird . Übrigens, ist die Verwendung von sednotwendig?
Barun
@Barun die Verwendung von sedist überhaupt nicht notwendig, ich dachte nur, das wäre die einfachste Option. Ich habe einen etwas anderen Code herausgefunden: Dieser sed -n "/AuthorYear/, /^ *\}/p"scheint genau das zu tun, was ich will, einschließlich des Schließens }und Korrigierens von Leerzeichen, falls vorhanden
Michiel,

Antworten:

1

Das folgende Python-Skript führt die gewünschte Filterung durch.

#!/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,

Persönlich bevorzuge ich den Wechsel zu einer Skriptsprache, wenn die Filterlogik komplex wird. Das hat vielleicht zumindest einen Vorteil für den Lesbarkeitsfaktor.

Barun
quelle
6

Ich würde empfehlen, eine Sprache mit einer kampferprobten BibTeX-Bibliothek zu verwenden, anstatt dieses Rad neu zu erfinden. Beispielsweise

#!/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->key eq "AuthorYear") {
        push @authoryear, $entry;
    }
}

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

Sie müssen wahrscheinlich das Modul installieren: cpan install BibTeX::Parser

Glenn Jackman
quelle
0

Dies ist ein Bash-Skript, das jede Zeile liest und Regex-Matching verwendet, um jeden Eintrag zu extrahieren, der das erforderliche Muster im Kopf hat. Sie können es getbibsoder so nennen:

#!/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"

Um alle Einträge mit einem Autorenjahr von 1989 zu extrahieren, haben Sie folgende Möglichkeiten:

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

Möglicherweise gibt es einige Probleme, die ich noch nicht getestet habe, aber es scheint für die Aufgabe in Ordnung zu sein.


quelle
0

Nur um ganz zu sein, wie ich es selbst herausgefunden habe, nicht so schön wie einige der anderen, aber es funktioniert:

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

Es kann über die Befehlszeile ausgeführt oder in ein Bash-Skript eingefügt werden.

Michiel
quelle
0

Jetzt haben wir auch das Python-Bibparsing-Modul, mit dem BibTeX-Datenbanken mit Python analysiert werden können. Zum Beispiel verwende ich das folgende Skript, um die Anzahl der Autoren in kollaborativen Artikeln zu berechnen:

#!/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])
wzab
quelle
0

Eine andere Möglichkeit wäre die Verwendung von bibtool.

Beispiel:

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

Lesen Sie das Handbuch für bestimmte Fälle.

Kirk Walla
quelle