Dynamically analyze BibTeX and create a hash hash

I am trying to parse the following BibTeX file (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} } 

I am using the BibTeX::Parser package, which works as expected, the problem is creating a hash of the hash structure. This is my code:

 #!/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 eg year -> 1996; isbn -> 1581138709 etc. foreach (@entries) { $article{"$_"} = $entry->field("$_"); } # return article 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); 

Output CURRENT Dumper (\%bibliography) :

 $VAR1 = { 'Lee2000a' => {}, 'Forrest1996' => $VAR1->{'Lee2000a'} }; 

DESIRED Dumper (\%bibliography) output 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' } }; 

What am I doing wrong? Thank you very much.

+4
source share
2 answers

Try the code without this line:

 # removes all elements of %article (prepare for next iteration) %article = (); 

You set $ bibilography {$ key} as a reference to this hash, and then you free it.

Also, wrap your% article declaration inside your loop (perhaps right after if ($entry->parse_ok) { , so its scope is local where you use it, and reinitialization is not necessary.

Hope this helps ...

Update to enable question sorting ... this should work to hash sort:

 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"; } } 
+2
source

Dump truck output

  $ VAR1 = {'Lee2000a' => {}, 'Forrest1996' => $ VAR1 -> {'Lee2000a'}}; 

shows that your hash is a separating structure, i.e. $bibliography->{Lee2000a} and $bibliography->{Forrest1996} are links to the same hash of the article. Your code has my %article in the outer scope, and each iteration of your loop clears and refills this shared hash.

Instead, you want each iteration to create a new internal hash of the article. Delete the external %article and move it to the marked loop (+) below. Delete the line %article = () , which will destroy the data you just collected.

 while ($entry = $parser->next) { if ($entry->parse_ok) { # return BibTeX elements like abstract, author, title ... @entries = $entry->fieldlist(); # create %article as a hash array eg year -> 1996; isbn -> 1581138709 etc. my %article; # (+) foreach (@entries) { $article{$_} = $entry->field($_); } # return article key (Lee2000a, Forrest1996) $key = $entry->key; # insert %article into %bibliography with appropriate key $bibliography{$key} = \%article; } else { warn "Error parsing file: " . $entry->error; } } 
+1
source

All Articles