Bibtex 파일에서 선택한 항목을 추출하는 스크립트


11

각 항목이 일반적인 구조를 갖는 많은 항목이있는 큰 bibtex 파일이 있습니다.

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

(어떤 경우 ARTICLE에는 다른 단어가있을 수 있습니다 BOOK)

내가하고 싶은 것은 주어진 AuthorYear로 항목을 추출하고 새로운 .bib 파일에 넣는 간단한 스크립트 (바람직하게는 쉘 스크립트)를 작성하는 것입니다.

AuthorYear의 첫 번째 문장과 마지막 닫힘으로 마지막 문장을 인식하고 항목 을 추출하는 데 }사용할 수 있다고 생각할 수 있지만 실제로이 sed작업을 정확히 수행하는 방법을 모르겠습니다. 누군가 내가 어떻게 이것을 달성 할 수 있는지 말해 줄 수 있습니까?

아마 다음과 같아야합니다

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

그러나 }항목의 첫 번째 항목이 닫히면 중지 되어 다음과 같이 출력됩니다.

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

따라서 }줄에서 유일한 문자 인지 여부를 인식해야 하며이 경우 읽기를 중지하십시오.


코드를 약간만 수정할 수 있습니다 sed -n "/AuthorYear/,/\}$/p". $기호를 참고하십시오 . }bibitem 의 닫힘 을 인쇄하지 않는다는 점을 제외하고는 잘 작동합니다 . Btw, 사용이 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}^}
vonbrand

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

이제 파이썬으로 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.