สคริปต์เพื่อแยกรายการที่เลือกจากไฟล์ bibtex


11

ฉันมีไฟล์ bibtex ขนาดใหญ่ที่มีหลายรายการที่แต่ละรายการมีโครงสร้างทั่วไป

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

(ในบางกรณีARTICLEอาจเป็นคำอื่นเช่นBOOK)

สิ่งที่ฉันต้องการจะทำคือเขียนสคริปต์ง่ายๆ (โดยเฉพาะอย่างยิ่งสคริปต์ shell) เพื่อแยกรายการที่มี AuthorYear ที่กำหนดและใส่ลงในไฟล์. ibib ใหม่

ฉันสามารถจินตนาการได้ว่าฉันสามารถจำประโยคแรกของรายการโดย AuthorYear และประโยคสุดท้ายด้วยการปิดครั้งเดียว}และอาจใช้sedเพื่อแยกรายการ แต่ฉันไม่รู้วิธีการทำสิ่งนี้อย่างแท้จริง มีคนบอกฉันได้ไหมว่าฉันจะทำสิ่งนี้ได้อย่างไร

มันน่าจะเป็นอะไรซักอย่าง

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

แต่นั่นจะหยุดเนื่องจากการปิด}ในรายการแรกของรายการจึงให้ผลลัพธ์นี้:

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

ดังนั้นฉันจึงจำเป็นต้องรู้ว่า}ตัวละครตัวนี้เป็นตัวเดียวในบรรทัดหรือไม่และมีเพียง 'sed' ที่จะหยุดอ่านเมื่อเป็นกรณีนี้


ฉันแก้ไขโค้ดของคุณได้เพียงเล็กน้อยsed -n "/AuthorYear/,/\}$/p"เท่านั้น: . สังเกต$สัญลักษณ์ มันทำงานได้ดียกเว้นว่ามันจะไม่พิมพ์ปิด}การบรรณานุกรม Btw การใช้งานsedจำเป็นหรือไม่?
Barun

@Bun การใช้งาน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,

โดยส่วนตัวแล้วฉันชอบที่จะย้ายไปใช้ภาษาสคริปต์เมื่อลอจิกการกรองซับซ้อน นั่นอาจมีข้อได้เปรียบในเรื่องความสามารถในการอ่านอย่างน้อย


ระวังมีหลายรายการด้วย{}s ที่ซ้อนกันอยู่ หากคุณมั่นใจได้ว่าการเข้ามาจบลงด้วย\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

ตอนนี้เรายังมี Python Bibparsing Module ที่ช่วยในการวิเคราะห์ฐานข้อมูล BibTeX ด้วย Python ตัวอย่างเช่นฉันใช้สคริปต์ต่อไปนี้เพื่อคำนวณจำนวนผู้แต่งในเอกสารความร่วมมือ:

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


0

นี่คือสคริปต์ Bash ซึ่งอ่านแต่ละบรรทัดและใช้การจับคู่ regex เพื่อแยกแต่ละรายการที่มีรูปแบบที่จำเป็นในส่วนหัว คุณสามารถโทร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

มันสามารถเรียกใช้จาก commandline หรือใส่ในสคริปต์ทุบตี

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.