我正在尝试解析以下BibTeX文件(bibliography.bib):
@book{Lee2000a,
abstract = {Abstract goes here},
author = {Lee, Wenke and Stolfo, Salvatore J},
title = {{Data mining approaches for intrusion detection}},
year = {2000}
}
@article{Forrest1996,
abstract = {Abstract goes here},
author = {Forrest, Stephanie and Hofmeyr, Steven A. and Anil, Somayaji},
title = {{Computer immunology}},
year = {1996}
}
我使用BibTeX::Parser
包按预期工作,问题是创建哈希结构的哈希。这是我的代码:
#!/usr/bin/perl
# http://search.cpan.org/~gerhard/BibTeX-Parser-0.62/lib/BibTeX/Parser.pm
use BibTeX::Parser;
use IO::File;
use Data::Dumper;
use strict;
use warnings;
my $filename="bibliography.bib";
my (%bibliography, %article);
my $i;
my ($entry, @entries, $type, $key);
my (my $hkey, my $hvalue);
# open BibTeX
my $fh = IO::File->new("$filename") or die "could not open $filename: $!\n";
# create parser object ...
my $parser = BibTeX::Parser->new($fh);
# ... and iterate over entries
while ($entry = $parser->next ) {
if ($entry->parse_ok) {
# return BibTeX elements like abstract, author, title ...
@entries = $entry->fieldlist();
# create %article as a hash array e.g. year -> 1996; isbn -> 1581138709 etc.
foreach (@entries) {
$article{"$_"} = $entry->field("$_");
}
# return article's key (Lee2000a, Forrest1996)
$key = $entry->key;
# append %article into %bibliography with approporiate key
$bibliography{"$key"} = \%article;
#Debug
#print $entry->key, "\n";
#print Dumper (\%article);
# removes all elements of %article (prepare for next iteration)
%article = ();
#Debug
#print "================================\n";
}
else {
warn "Error parsing file: " . $entry->error;
}
}
#Debug
#print Dumper (\%bibliography);
Dumper (\%bibliography)
的当前输出:
$VAR1 = {
'Lee2000a' => {},
'Forrest1996' => $VAR1->{'Lee2000a'}
};
Dumper (\%bibliography)
的渴望输出:
$VAR1 = {
'Lee2000a' => {
'abstract' => 'Abstract goes here',
'author' => 'Lee, Wenke and Stolfo, Salvatore J'
'title' => 'Data mining approaches for intrusion detection'
'year' => '2000'
},
'Forrest1996' => {
'abstract' => 'Abstract goes here',
'author' => 'Forrest, Stephanie and Hofmeyr, Steven A. and Anil, Somayaji'
'title' => 'Computer immunology'
'year' => '1996'
}
};
我做错了什么?非常感谢。
答案 0 :(得分:2)
尝试不带此行的代码:
# removes all elements of %article (prepare for next iteration)
%article = ();
您已将$ bibilography {$ key}设置为该哈希的引用,然后您将其清空。
另外,在你的循环中移动你的%article声明(可能就在if ($entry->parse_ok) {
之后,以便它的范围是你使用它的本地范围,并且不需要重新初始化它。
希望有帮助...
更新以包括排序问题...这应该可以对哈希进行排序:
foreach my $bib_key ( sort keys %bibliography ) {
print "$bib_key\n";
foreach my $article_key (sort keys %{ $bibliography{$bib_key} }) {
print "\t $article_key: $bibliography{$bib_key}{$article_key}\n";
}
}
答案 1 :(得分:1)
Dumper输出
$VAR1 = { 'Lee2000a' => {}, 'Forrest1996' => $VAR1->{'Lee2000a'} };
表明您的哈希是共享结构,即。,$bibliography->{Lee2000a}
和$bibliography->{Forrest1996}
是对相同文章哈希的引用。您的代码在外部作用域中有my %article
,并且循环的每次迭代都会清除并重新填充此共享散列。
相反,您希望每次迭代都创建一个 new 内部文章哈希。移除外部%article
并将其移动到下面的循环标记(+)中。删除%article = ()
行,这会破坏您刚刚收集的数据。
while ($entry = $parser->next) {
if ($entry->parse_ok) {
# return BibTeX elements like abstract, author, title ...
@entries = $entry->fieldlist();
# create %article as a hash array e.g. year -> 1996; isbn -> 1581138709 etc.
my %article; # (+)
foreach (@entries) {
$article{$_} = $entry->field($_);
}
# return article's key (Lee2000a, Forrest1996)
$key = $entry->key;
# insert %article into %bibliography with appropriate key
$bibliography{$key} = \%article;
}
else {
warn "Error parsing file: " . $entry->error;
}
}