У меня есть большой текстовый файл (.bib) с множеством двойных записей для некоторых полей. По сути, файл представляет собой файл .bib (более подробную информацию здесь), который содержит около 1000 записей. Содержание структурировано так:

@Article{Apak_2011_Financialriskmanagement,
Title                    = {Financial risk management in renewable energy sector: Comparative analysis between the European Union and Turkey},
Author                   = {Apak, Sudi and Atay, Erhan and Tuncer, Güngör},
Journal                  = {Procedia - Social and Behavioral Sciences},
Pages                    = {935--945},
Volume                   = {24},
Year                     = {2011},
Doi                      = {10.1016/j.sbspro.2011.09.013},
ISSN                     = {1877-0428},
}

@Incollection{Berger_1992_OutputMeasurementin,
Title                    = {Output Measurement in the Service Sectors},
Author                   = {Berger, Allen N. and Humphrey, David B.},
Crossref                 = {Griliches_1992_OutputMeasurementinb},
Pages                    = {245--300 book},
Year                     = {1992},
Publisher                = {University of Chicago Press},
Date                    = {1992-10-04},
Booktitle                = {Output Measurement in the Service Sectors},
Editor                   = {Griliches, Zvi and Berndt, Ernst R. and Bresnahan, Timothy F. and Manser, Marilyn}
}

@Book{Bogenstahl_2012_ManagementvonNetzwerken,
  Title                    = {Management von Netzwerken},
  Author                   = {Bogenstahl, Christoph},
  Publisher                = {Gabler},
  Date                     = {2012-01-01},
  ISBN                     = {978-3-8349-3572-4},
  Series                   = {Strategisches Kompetenz-Management}
}

Вы увидите, что для первого источника определен только Year . Однако во втором источнике определены Year и Date .

РЕДАКТИРОВАТЬ: HINDSIGHT 20/20

Я только что заметил, что мне всегда нужно поле Year потому что я управляю всем файлом через JabRef. А для генерации bibtex-ключа JabRef необходимо поле Year . Я имею в виду, что до сих пор не нашел возможности сгенерировать ключ bibtex с помощью yyyy части поля Date , поэтому я отредактирую условия.

Итак, есть ли способ сделать следующие действия:

  • Если для исходной записи определена только Date , скопируйте первые 4 цифры (гггг) в Year .
  • Если задан только Year , скопируйте четыре цифры в Date .
  • Если определены Date и Year , ничего не делайте.

Далее следуют старые условия, когда я заранее не думал о внутренней работе JabRef.

Старые условия, все еще уместные, если кто-то хотел бы подготовить .bib-файл для использования с biblatex и имеет в своем файле перепутанные поля Date и Year :

  • Если для исходной записи определена только Date , ничего не делайте.
  • Если определены Date и Year , скопируйте содержимое скобок для Date в скобки для Year . Подвох в том, что Date может содержать больше информации (в формате yyyy-mm-dd), чем Year , поэтому я и записываю эти "условия". Независимо от содержания Year , Date важнее. Если я не допустил ошибок при вводе всей информации, первые 4 цифры Date конечно, должны быть равны Year .
  • Если определен только Year , термин « Year можно просто заменить на Date .

Несколько заметок:

  • Если эта информация может помочь в этом случае: я использую Windows 7 и Xubuntu 14.04. У меня есть Office 2010, если это можно использовать здесь ... или я мог бы с удовольствием использовать какой-то инструмент на Xubuntu, я не знаю.

  • Я уже проверил и, видимо, я не могу использовать JabRef для этого, это слишком сложно.

2 ответа2

2

Я бы бросил Perl на эту проблему. http://search.cpan.org/~ambs/Text-BibTeX-0.70/lib/Text/BibTeX.pm должен помочь. Что-то вроде:

use Text::BibTeX;

$bibfile = new Text::BibTeX::File "foo.bib";
$newfile = new Text::BibTeX::File ">newfoo.bib";

while ($entry = new Text::BibTeX::Entry $bibfile) {
    next unless $entry->parse_ok;

    if ($has_year = $entry->exists ('year')) {
        $year = $entry->get('year');
    }
    if ($has_date = $entry->exists ('date')) {
        $date = $entry->get('date');
    }
    if ($has_year and ! $has_date) {
        $entry->set('date', $year);
    }
    if ($has_date and ! $has_year) {
        $entry->set('year', substr($date, 0, 4));
    }
    $entry->write ($newfile);
}
1

ПРИМЕЧАНИЕ. Это решение предназначено для первоначального набора требований. Это должно быть обновлено для работы с текущей версией. А также, ответ на основе perl любом случае намного чище :-)

Если вы не возражаете против создания некоторых временных файлов, это может быть отправной точкой: скопируйте это в файл и установите флаг исполняемого файла (chmod +x file)

#!/bin/bash
INFILE=$1

# split the file first
awk '/^@/{x="tmp__"++i}{print > x;}' $INFILE

# process individual files
for file in tmp__* ; do 
    DATE=$(grep "^[[:space:]]*Date" $file | sed "s/.*{\(.*\)}.*/\1/g")
    YEAR=$(grep "^[[:space:]]*Year" $file | sed "s/.*{\(.*\)}.*/\1/g")

    # Both year and date. Substitute year with date
    if [[ -n "$DATE" && -n "$YEAR" ]] ; then
        sed -i "s/\(^[[:space:]]*Year.*\)${YEAR}\(.*\)/\1${DATE}\2/g" $file
    fi

    # Only year
    if [[ -z "$DATE" && -n "$YEAR" ]] ; then
        sed -i "s/\(^[[:space:]]*\)Year/\1Date/g" $file
    fi
done

# concatenate the files back
cat tmp__* > out.bib
rm -f tmp__*

Что делает скрипт:

  • Принимает один параметр - имя входного файла
  • Разбивает файл на несколько временных файлов, каждый из которых содержит только одну запись
  • перебирает файлы и обрабатывает их индивидуально в соответствии с вашими инструкциями (при условии, что я их хорошо понял, то есть - см. ниже)
  • объединяет обработанные файлы в out.bib
  • удаляет временные файлы

Скрипт не изменяет исходный входной файл, поэтому он должен быть довольно безопасным.

Я до сих пор не до конца понимаю ваши требования, поэтому, если вы попробуете и найдете несколько случаев, когда это не будет соответствовать вашим ожиданиям, не стесняйтесь, дайте мне знать, и я постараюсь улучшить его.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .