Bib2wiki: Difference between revisions
Fabrice P. Laussy's Web
Fabrice (talk | contribs)
New script for referencing on this web
 
Fabrice (talk | contribs)
m 1 revision imported
 
(18 intermediate revisions by 3 users not shown)
Line 1: Line 1:
= bib2wiki =
= bib2wiki =


'''''bib2wiki''''' is a [[perl]] script to generate a [[template]] to cite scientific refeferences on this [[laussy.org|very website]] from its [[bibTeX|$\mathrm{B{\scriptstyle{IB}}\TeX}$]] entry.
'''''bib2wiki''''' is a [[perl]] script to generate a [[template]] to cite scientific references on this [[laussy.org|very website]] from its [[bibTeX|$\mathrm{B{\scriptstyle{IB}}\TeX}$]] entry.


The rationale is explained [[Blog:Hacks/A_simple_way_to_quote_from_bibTeX_in_MediaWiki|in this blog post]].
This is, for instance, an old paper of ours: {{delvalle07a}}
 
The rationale is explained [[Blog:Hacks/A_simple_way_to_quote_from_bibTeX_in_MediaWiki|in this blog post]] and '''[[Blog:Hacks/bib2wiki_or_parsing_bibTeX_into_mediawiki_templates|examples of its use are in this other blog post]]'''. Undefined references can be fixed with '''[[keys2wiki]]'''.
 
It supports [[Bash]] autocompletion, as is declared in [[showme]].


It is based on [https://metacpan.org/pod/BibTeX::Parser BibTeX::Parser].
It is based on [https://metacpan.org/pod/BibTeX::Parser BibTeX::Parser].
Line 11: Line 15:
<pre>
<pre>
# Usage:  
# Usage:  
# To print everything:
#  bib2wiki -keys=all
#
# To print one key:
# To print one key:
#  bib2wiki -keys=laussy04a
#  bib2wiki laussy04a
#
#
# To print several keys:
# To print several keys:
#  bib2wiki -keys=laussy04a,laussy05a,laussy06a
#  bib2wiki -keys=laussy04a,laussy05a,laussy06a
#
# To print everything:
#  bib2wiki -keys=all
</pre>
</pre>


== Get the keys from Mediawiki ==
== Script ==


To extract the keys needed on a page, in edit mode, look for the list of templates at the end. It could look something like this:
* All versions till v0°5 were written on {{thisday|16|July|2023}}.
* v0°6 was written on {{thisday|22|October|2023}} to interface with [[keys2wiki]] (clearing the screen).
* [[Blog:Trifles/v0°7 of bib2wiki|v0°7]] was written on {{thisday|31|December|2023}}.
* v1°0 was updated on {{thisday|16|September|2025}} — it merely outputs the key in bold yellow (and fixes the î which requires special escape), but the code is robust and useful enough to warrant a 1.0 label.
* v1.1 Tue Sep 16 2025 - retain same order of keys
* v1.2 Sun Sep 21 - also process arXiv.bib
* v1.3 Sun Sep 21 2025 - special formatting for arXiv entries
* v1.4 Sun Sep 21 2025 - fix <nowiki><wz></nowiki> tag placement
* v1.5 Sun Sep 21 2025 - fix <nowiki>{{arXiv}}</nowiki> template syntax
* v1.6 Mon Sep 22 2025 - all diatrics Grok can think of


<wz tip="References not yet uploaded to the wiki.">[[File:Screenshot_20230716_164012.png|250px]]</wz>
<syntaxhighlight lang="perl">
#!/usr/bin/perl -X -s
# _    _ _    ____          _ _    _
#| |__ (_) |__|___ \__      _(_) | _(_)
#| '_ \| | '_ \ __) \ \ /\ / / | |/ / |
#| |_) | | |_) / __/ \ V  V /| |  <| |
#|_.__/|_|_.__/_____| \_/\_/ |_|_|\_\_|
# F.P. Laussy - fabrice.laussy@gmailcom
# v0°5 Sun 16 Jul 2023
# v0°7 Sun 31 Dec 2023 - http://laussy.org/wiki/Blog:Trifles/v0%C2%B07_of_bib2wiki
# v1.1 Tue Sep 16 2025 - retain same order of keys
# v1.2 Sun Sep 21 - also process arXiv.bib
# v1.3 Sun Sep 21 2025 - special formatting for arXiv entries
# v1.4 Sun Sep 21 2025 - fix <wz> tag placement
# v1.5 Sun Sep 21 2025 - fix {{arXiv}} template syntax
# v1.6 Mon Sep 22 2025 - all diatrics Grok can think of


Copy/past in a file (say <tt>templates</tt>) on which you run:
use BibTeX::Parser;
use IO::File;


<pre>
# clear screen
cat templates | perl -pe 's/Template:([a-zA-Z]+[0-9]{2}[a-z])\s\(edit\)\.*/\1/p' | sed '/Template/d' | awk -vORS=, '{ print $1 }' | sed 's/,$/\n/'
import os;
</pre>
#os.system('clear');
 
# This is to remove warnings from the bibTeX parser:
use File::Spec;
open STDERR, '>', File::Spec->devnull();
 
# Concatenate sci.bib and arXiv.bib into an in-memory filehandle
my $file1 = "/home/laussy/bib/sci.bib";
my $file2 = "/home/laussy/bib/arXiv.bib";
my $content = '';
my $fh1 = IO::File->new($file1, 'r') or die "Cannot open $file1: $!\n";
$content .= $_ while <$fh1>;
$fh1->close;
my $fh2 = IO::File->new($file2, 'r') or die "Cannot open $file2: $!\n";
$content .= $_ while <$fh2>;
$fh2->close;
my $fh = IO::File->new(\$content, 'r') or die "Cannot create filehandle from content: $!\n";
 
my $parser = BibTeX::Parser->new($fh);
 
# the map lc converts to lowercases
#my @mykeys =  map { lc } split(/,/, $keys); ## doesn't work with arXiv
my @mykeys =  split(/,/, $keys);
 
push(@mykeys,$ARGV[0]);
 
# If keys is "all", process all entries in file order
if ($keys eq "all") {
    while (my $entry = $parser->next) {
        if ($entry->parse_ok) {
            my $bibkey = $entry->key;
            my $type = $entry->type;
            my $title = $entry->field("title");
            my $url = $entry->field("url") || "";
            my $journal = $entry->field("journal") || "";
            my $volume = $entry->field("volume") || "";
            my $pages = $entry->field("pages") || "";
            my $year = $entry->field("year");
 
            print "\033[1;31m$bibkey\033[0m\n";
            my $output = "";
 
            my @authors = $entry->author;
            my @notlast = @authors;
            pop @notlast;
 
            foreach my $author (@notlast) {
                my $initials = $author->first;
                $initials =~ s/~/ /g;
                $output .= "[[" . $initials . " " . $author->von . " " . $author->last . "]], ";
            }
 
            my $initials = $authors[-1]->first;
            $initials =~ s/~//g;
            if (@notlast) { $output .= "and "; }
            $output .= "[[" . $initials . " " . $authors[-1]->von . " " . $authors[-1]->last . "]] in ";
 
            # Check if the entry is from arXiv
            if ($journal =~ /arXiv/i || $url =~ /arXiv/i) {
                # Extract arXiv ID from URL or journal
                my $arxiv_id = "";
                if ($url =~ /arXiv\.(\d+\.\d+)/i) {
                    $arxiv_id = $1;
                } elsif ($journal =~ /arXiv:(\d+\.\d+)/i) {
                    $arxiv_id = $1;
                }
                $output = "<wz tip=\"$arxiv_id\">[[File:arXXXiv.png|20px|link=]]</wz><u>[[" . $bibkey . "|" . $title . "]]</u>. " . $output . "\{\{arXiv|$arxiv_id\}\} ([[" . $year . "]]).\n\n";
            } else {
                $url =~ s/doi:/http:\/\/dx.doi.org\//;
                $output = "<u>[[" . $bibkey . "|" . $title . "]]</u>. " . $output . "[[" . $journal . "]] [" . $url . " '''" . $volume . "''':" . $pages . "] ([[" . $year . "]]).\n\n";
            }
 
            # Apply existing substitutions
            $output =~ s/, and/ and/g;
            $output =~ s/ +/ /g;
            $output =~ s/--/-/g;
            $output =~ s/{//g;
            $output =~ s/}//g;
            $output =~ s/\\'a/á/g;
            $output =~ s/\\'e/é/g;
            $output =~ s/\\`e/è/g;
            $output =~ s/\\'i/í/g;
            $output =~ s/\\'o/ó/g;
            $output =~ s/\\"a/ä/g;
            $output =~ s/\\"o/ö/g;
            $output =~ s/\\"u/ü/g;
            $output =~ s/\\~n/ñ/g;
            $output =~ s/\\'n/ń/g;
            $output =~ s/\\'E/É/g;
            $output =~ s/\\\^i/î/g;
            $output =~ s/\\Imamoglu/İmamoğlu/g;
            $output =~ s/\\Vuckovic/Vučković/g;
 
            print $output;
        } else {
            warn "Error parsing file: " . $entry->error;
        }
    }
} else {
    # Process keys in the order they were provided in @mykeys
    foreach my $key (@mykeys) {
        # Reset parser to start of file
        $fh->seek(0, 0);  # Rewind file handle
        my $parser = BibTeX::Parser->new($fh);  # Create new parser instance
        while (my $entry = $parser->next) {
            if ($entry->parse_ok && $entry->key eq $key) {
                my $bibkey = $entry->key;
                my $type = $entry->type;
                my $title = $entry->field("title");
                my $url = $entry->field("url") || "";
                my $journal = $entry->field("journal") || "";
                my $volume = $entry->field("volume") || "";
                my $pages = $entry->field("pages") || "";
                my $year = $entry->field("year");


That will output on one line the list of templates needed:
                print "\033[1;31m$bibkey\033[0m\n";
                my $output = "";


<pre>
                my @authors = $entry->author;
Kirkwood35a,Kirkwood39a,Kirkwood42a,Kirkwood50a,Lopezcarreno18b,Percus58a,Salsburg53a,Sells53a,Thiele63a,Wertheim63a,Zerniker37a
                my @notlast = @authors;
</pre>
                pop @notlast;


You can then pass this to bib2wiki
                foreach my $author (@notlast) {
                    my $initials = $author->first;
                    $initials =~ s/~/ /g;
                    $output .= "[[" . $initials . " " . $author->von . " " . $author->last . "]], ";
                }


<pre>
                my $initials = $authors[-1]->first;
bib2wiki -keys=Kirkwood35a,Kirkwood39a,Kirkwood42a,Kirkwood50a,Lopezcarreno18b,Percus58a,Salsburg53a,Sells53a,Thiele63a,Wertheim63a,Zerniker37a
                $initials =~ s/~//g;
</pre>
                if (@notlast) { $output .= "and "; }
                $output .= "[[" . $initials . " " . $authors[-1]->von . " " . $authors[-1]->last . "]] in ";


which will return the list you have to upload:
                # Check if the entry is from arXiv
                if ($journal =~ /arXiv/i || $url =~ /arXiv/i) {
                    # Extract arXiv ID from URL or journal
                    my $arxiv_id = "";
                    if ($url =~ /arXiv\.(\d+\.\d+)/i) {
                        $arxiv_id = $1;
                    } elsif ($journal =~ /arXiv:(\d+\.\d+)/i) {
                        $arxiv_id = $1;
                    }
                    $output = "<wz tip=\"arXiv:$arxiv_id\">[[File:arXXXiv.png|14px|link=]]</wz><u>[[" . $bibkey . "|" . $title . "]]</u>. " . $output . "\{\{arXiv|$arxiv_id\}\} ([[" . $year . "]]).\n\n";
                } else {
                    $url =~ s/doi:/http:\/\/dx.doi.org\//;
                    $output = "<u>[[" . $bibkey . "|" . $title . "]]</u>. " . $output . "[[" . $journal . "]] [" . $url . " '''" . $volume . "''':" . $pages . "] ([[" . $year . "]]).\n\n";
                }


<pre>
                # Apply existing substitutions
kirkwood35a
$output =~ s/{{/XXXopenXXX/g;
<u>[[Statistical Mechanics of Fluid Mixtures]]</u>. [[J. G. Kirkwood]] in [[J. Chem. Phys.]] [http://dx.doi.org/10.1063/1.1749657 '''3''':300] ([[1935]]).
$output =~ s/}}/XXXcloseXXX/g;
                $output =~ s/, and/ and/g;
                $output =~ s/ +/ /g;
                $output =~ s/--/-/g;
                $output =~ s/{//g;
                $output =~ s/}//g;


kirkwood39a
$output =~ s/\\"A/Ä/g;
<u>[[Molecular Distribution in Liquids]]</u>. [[J. G. Kirkwood]] in [[J. Chem. Phys.]] [http://dx.doi.org/10.1063/1.1750344 '''7''':919] ([[1939]]).
$output =~ s/\\"E/Ë/g;
$output =~ s/\\"I/Ï/g;
$output =~ s/\\"O/Ö/g;
$output =~ s/\\"U/Ü/g;
$output =~ s/\\"Y/Ÿ/g;
$output =~ s/\\"a/ä/g;
$output =~ s/\\"e/ë/g;
$output =~ s/\\"i/ï/g;
$output =~ s/\\"o/ö/g;
$output =~ s/\\"u/ü/g;
$output =~ s/\\"y/ÿ/g;
$output =~ s/\\'A/Á/g;
$output =~ s/\\'E/É/g;
$output =~ s/\\'I/Í/g;
$output =~ s/\\'O/Ó/g;
$output =~ s/\\'U/Ú/g;
$output =~ s/\\'Y/Ý/g;
$output =~ s/\\'a/á/g;
$output =~ s/\\'c/ć/g;
$output =~ s/\\'e/é/g;
$output =~ s/\\'i/í/g;
$output =~ s/\\'l/ĺ/g;
$output =~ s/\\'n/ń/g;
$output =~ s/\\'o/ó/g;
$output =~ s/\\'r/ŕ/g;
$output =~ s/\\'s/ś/g;
$output =~ s/\\'u/ú/g;
$output =~ s/\\'y/ý/g;
$output =~ s/\\'z/ź/g;
$output =~ s/\\.Z/Ż/g;
$output =~ s/\\.e/ė/g;
$output =~ s/\\.g/ġ/g;
$output =~ s/\\.z/ż/g;
$output =~ s/\\=A/Ā/g;
$output =~ s/\\=E/Ē/g;
$output =~ s/\\=I/Ī/g;
$output =~ s/\\=O/Ō/g;
$output =~ s/\\=U/Ū/g;
$output =~ s/\\=a/ā/g;
$output =~ s/\\=e/ē/g;
$output =~ s/\\=i/ī/g;
$output =~ s/\\=o/ō/g;
$output =~ s/\\=u/ū/g;
$output =~ s/\\AA/Å/g;
$output =~ s/\\AE/Æ/g;
$output =~ s/\\DH/Ð/g;
$output =~ s/\\HO/Ő/g;
$output =~ s/\\HU/Ű/g;
$output =~ s/\\Ho/ő/g;
$output =~ s/\\Hu/ű/g;
$output =~ s/\\L/Ł/g;
$output =~ s/\\O/Ø/g;
$output =~ s/\\OE/Œ/g;
$output =~ s/\\TH/Þ/g;
$output =~ s/\\`A/À/g;
$output =~ s/\\`E/È/g;
$output =~ s/\\`I/Ì/g;
$output =~ s/\\`O/Ò/g;
$output =~ s/\\`U/Ù/g;
$output =~ s/\\`a/à/g;
$output =~ s/\\`e/è/g;
$output =~ s/\\`i/ì/g;
$output =~ s/\\`o/ò/g;
$output =~ s/\\`u/ù/g;
$output =~ s/\\aa/å/g;
$output =~ s/\\ae/æ/g;
$output =~ s/\\c e/ę/g;
$output =~ s/\\cC/Ç/g;
$output =~ s/\\cc/ç/g;
$output =~ s/\\cg/ģ/g;
$output =~ s/\\ck/ķ/g;
$output =~ s/\\cl/ļ/g;
$output =~ s/\\cn/ņ/g;
$output =~ s/\\cr/ŗ/g;
$output =~ s/\\cs/ş/g;
$output =~ s/\\ct/ţ/g;
$output =~ s/\\dh/ð/g;
$output =~ s/\\kA/Ą/g;
$output =~ s/\\kE/Ę/g;
$output =~ s/\\kI/Į/g;
$output =~ s/\\kU/Ų/g;
$output =~ s/\\ka/ą/g;
$output =~ s/\\ke/ę/g;
$output =~ s/\\ki/į/g;
$output =~ s/\\ku/ų/g;
$output =~ s/\\l/ł/g;
$output =~ s/\\o/ø/g;
$output =~ s/\\oe/œ/g;
$output =~ s/\\ss/ß/g;
$output =~ s/\\th/þ/g;
$output =~ s/\\uA/Ă/g;
$output =~ s/\\uE/Ĕ/g;
$output =~ s/\\uG/Ğ/g;
$output =~ s/\\uI/Ĭ/g;
$output =~ s/\\uO/Ŏ/g;
$output =~ s/\\uU/Ŭ/g;
$output =~ s/\\ua/ă/g;
$output =~ s/\\ue/ĕ/g;
$output =~ s/\\ug/ğ/g;
$output =~ s/\\ui/ĭ/g;
$output =~ s/\\uo/ŏ/g;
$output =~ s/\\uu/ŭ/g;
$output =~ s/\\vA/Ǎ/g;
$output =~ s/\\vC/Č/g;
$output =~ s/\\vD/Ď/g;
$output =~ s/\\vE/Ě/g;
$output =~ s/\\vL/Ľ/g;
$output =~ s/\\vN/Ň/g;
$output =~ s/\\vR/Ř/g;
$output =~ s/\\vS/Š/g;
$output =~ s/\\vT/Ť/g;
$output =~ s/\\vU/Ů/g;
$output =~ s/\\vZ/Ž/g;
$output =~ s/\\va/ǎ/g;
$output =~ s/\\vc/č/g;
$output =~ s/\\vd/ď/g;
$output =~ s/\\ve/ě/g;
$output =~ s/\\vl/ľ/g;
$output =~ s/\\vn/ň/g;
$output =~ s/\\vr/ř/g;
$output =~ s/\\vs/š/g;
$output =~ s/\\vt/ť/g;
$output =~ s/\\vu/ů/g;
$output =~ s/\\vz/ž/g;
$output =~ s/\\~A/Ã/g;
$output =~ s/\\~N/Ñ/g;
$output =~ s/\\~O/Õ/g;
$output =~ s/\\~a/ã/g;
$output =~ s/\\~n/ñ/g;
$output =~ s/\\~o/õ/g;
$output =~ s/\\^A/Â/g;
$output =~ s/\\^E/Ê/g;
$output =~ s/\\^I/Î/g;
$output =~ s/\\^O/Ô/g;
$output =~ s/\\^U/Û/g;
$output =~ s/\\^Y/Ŷ/g;
$output =~ s/\\^a/â/g;
$output =~ s/\\^e/ê/g;
$output =~ s/\\^i/î/g;
$output =~ s/\\^o/ô/g;
$output =~ s/\\^u/û/g;
$output =~ s/\\^y/ŷ/g;


kirkwood42a
                $output =~ s/\\Imamoglu/İmamoğlu/g;
<u>[[The Radial Distribution Function in Liquids]]</u>. [[J. G. Kirkwood]] and [[E. Monroe]] in [[J. Chem. Phys.]] [http://dx.doi.org/10.1063/1.1723737 '''10''':394] ([[1942]]).
                $output =~ s/\\Vuckovic/Vučković/g;
$output =~ s/XXXopenXXX/{{/g;
$output =~ s/XXXcloseXXX/}}/g;


etc.
                print $output;
</pre>
                last;  # Exit inner loop once key is found
            }
        }
    }
}
</syntaxhighlight>

Latest revision as of 01:18, 31 December 2025

bib2wiki

bib2wiki is a perl script to generate a template to cite scientific references on this very website from its $\mathrm{B{\scriptstyle{IB}}\TeX}$ entry.

This is, for instance, an old paper of ours: Electrostatic control of quantum dot entanglement induced by coupling to external reservoirs. E. del Valle, F. P. Laussy and C. Tejedor in Europhys. Lett. 80:57001 (2007).

The rationale is explained in this blog post and examples of its use are in this other blog post. Undefined references can be fixed with keys2wiki.

It supports Bash autocompletion, as is declared in showme.

It is based on BibTeX::Parser.

Usage

# Usage: 
# To print one key:
#   bib2wiki laussy04a
#
# To print several keys:
#   bib2wiki -keys=laussy04a,laussy05a,laussy06a
#
# To print everything:
#   bib2wiki -keys=all

Script

  • All versions till v0°5 were written on 16 July (2023).
  • v0°6 was written on 22 October (2023) to interface with keys2wiki (clearing the screen).
  • v0°7 was written on 31 December (2023).
  • v1°0 was updated on 16 September (2025) — it merely outputs the key in bold yellow (and fixes the î which requires special escape), but the code is robust and useful enough to warrant a 1.0 label.
  • v1.1 Tue Sep 16 2025 - retain same order of keys
  • v1.2 Sun Sep 21 - also process arXiv.bib
  • v1.3 Sun Sep 21 2025 - special formatting for arXiv entries
  • v1.4 Sun Sep 21 2025 - fix <wz> tag placement
  • v1.5 Sun Sep 21 2025 - fix {{arXiv}} template syntax
  • v1.6 Mon Sep 22 2025 - all diatrics Grok can think of
#!/usr/bin/perl -X -s
# _     _ _    ____           _ _    _ 
#| |__ (_) |__|___ \__      _(_) | _(_)
#| '_ \| | '_ \ __) \ \ /\ / / | |/ / |
#| |_) | | |_) / __/ \ V  V /| |   <| |
#|_.__/|_|_.__/_____| \_/\_/ |_|_|\_\_|
# F.P. Laussy - fabrice.laussy@gmailcom
# v0°5 Sun 16 Jul 2023
# v0°7 Sun 31 Dec 2023 - http://laussy.org/wiki/Blog:Trifles/v0%C2%B07_of_bib2wiki
# v1.1 Tue Sep 16 2025 - retain same order of keys
# v1.2 Sun Sep 21 - also process arXiv.bib
# v1.3 Sun Sep 21 2025 - special formatting for arXiv entries
# v1.4 Sun Sep 21 2025 - fix <wz> tag placement
# v1.5 Sun Sep 21 2025 - fix {{arXiv}} template syntax
# v1.6 Mon Sep 22 2025 - all diatrics Grok can think of

use BibTeX::Parser;
use IO::File;

# clear screen
import os;
#os.system('clear');

# This is to remove warnings from the bibTeX parser:
use File::Spec;
open STDERR, '>', File::Spec->devnull();

# Concatenate sci.bib and arXiv.bib into an in-memory filehandle
my $file1 = "/home/laussy/bib/sci.bib";
my $file2 = "/home/laussy/bib/arXiv.bib";
my $content = '';
my $fh1 = IO::File->new($file1, 'r') or die "Cannot open $file1: $!\n";
$content .= $_ while <$fh1>;
$fh1->close;
my $fh2 = IO::File->new($file2, 'r') or die "Cannot open $file2: $!\n";
$content .= $_ while <$fh2>;
$fh2->close;
my $fh = IO::File->new(\$content, 'r') or die "Cannot create filehandle from content: $!\n";

my $parser = BibTeX::Parser->new($fh);

# the map lc converts to lowercases
#my @mykeys =  map { lc } split(/,/, $keys); ## doesn't work with arXiv
my @mykeys =  split(/,/, $keys);

push(@mykeys,$ARGV[0]);

# If keys is "all", process all entries in file order
if ($keys eq "all") {
    while (my $entry = $parser->next) {
        if ($entry->parse_ok) {
            my $bibkey = $entry->key;
            my $type = $entry->type;
            my $title = $entry->field("title");
            my $url = $entry->field("url") || "";
            my $journal = $entry->field("journal") || "";
            my $volume = $entry->field("volume") || "";
            my $pages = $entry->field("pages") || "";
            my $year = $entry->field("year");

            print "\033[1;31m$bibkey\033[0m\n";
            my $output = "";

            my @authors = $entry->author;
            my @notlast = @authors;
            pop @notlast;

            foreach my $author (@notlast) {
                my $initials = $author->first;
                $initials =~ s/~/ /g;
                $output .= "[[" . $initials . " " . $author->von . " " . $author->last . "]], ";
            }

            my $initials = $authors[-1]->first;
            $initials =~ s/~//g;
            if (@notlast) { $output .= "and "; }
            $output .= "[[" . $initials . " " . $authors[-1]->von . " " . $authors[-1]->last . "]] in ";

            # Check if the entry is from arXiv
            if ($journal =~ /arXiv/i || $url =~ /arXiv/i) {
                # Extract arXiv ID from URL or journal
                my $arxiv_id = "";
                if ($url =~ /arXiv\.(\d+\.\d+)/i) {
                    $arxiv_id = $1;
                } elsif ($journal =~ /arXiv:(\d+\.\d+)/i) {
                    $arxiv_id = $1;
                }
                $output = "<wz tip=\"$arxiv_id\">[[File:arXXXiv.png|20px|link=]]</wz><u>[[" . $bibkey . "|" . $title . "]]</u>. " . $output . "\{\{arXiv|$arxiv_id\}\} ([[" . $year . "]]).\n\n";
            } else {
                $url =~ s/doi:/http:\/\/dx.doi.org\//;
                $output = "<u>[[" . $bibkey . "|" . $title . "]]</u>. " . $output . "[[" . $journal . "]] [" . $url . " '''" . $volume . "''':" . $pages . "] ([[" . $year . "]]).\n\n";
            }

            # Apply existing substitutions
            $output =~ s/, and/ and/g;
            $output =~ s/ +/ /g;
            $output =~ s/--/-/g;
            $output =~ s/{//g;
            $output =~ s/}//g;
            $output =~ s/\\'a/á/g;
            $output =~ s/\\'e/é/g;
            $output =~ s/\\`e/è/g;
            $output =~ s/\\'i/í/g;
            $output =~ s/\\'o/ó/g;
            $output =~ s/\\"a/ä/g;
            $output =~ s/\\"o/ö/g;
            $output =~ s/\\"u/ü/g;
            $output =~ s/\\~n/ñ/g;
            $output =~ s/\\'n/ń/g;
            $output =~ s/\\'E/É/g;
            $output =~ s/\\\^i/î/g;
            $output =~ s/\\Imamoglu/İmamoğlu/g;
            $output =~ s/\\Vuckovic/Vučković/g;

            print $output;
        } else {
            warn "Error parsing file: " . $entry->error;
        }
    }
} else {
    # Process keys in the order they were provided in @mykeys
    foreach my $key (@mykeys) {
        # Reset parser to start of file
        $fh->seek(0, 0);  # Rewind file handle
        my $parser = BibTeX::Parser->new($fh);  # Create new parser instance
        while (my $entry = $parser->next) {
            if ($entry->parse_ok && $entry->key eq $key) {
                my $bibkey = $entry->key;
                my $type = $entry->type;
                my $title = $entry->field("title");
                my $url = $entry->field("url") || "";
                my $journal = $entry->field("journal") || "";
                my $volume = $entry->field("volume") || "";
                my $pages = $entry->field("pages") || "";
                my $year = $entry->field("year");

                print "\033[1;31m$bibkey\033[0m\n";
                my $output = "";

                my @authors = $entry->author;
                my @notlast = @authors;
                pop @notlast;

                foreach my $author (@notlast) {
                    my $initials = $author->first;
                    $initials =~ s/~/ /g;
                    $output .= "[[" . $initials . " " . $author->von . " " . $author->last . "]], ";
                }

                my $initials = $authors[-1]->first;
                $initials =~ s/~//g;
                if (@notlast) { $output .= "and "; }
                $output .= "[[" . $initials . " " . $authors[-1]->von . " " . $authors[-1]->last . "]] in ";

                # Check if the entry is from arXiv
                if ($journal =~ /arXiv/i || $url =~ /arXiv/i) {
                    # Extract arXiv ID from URL or journal
                    my $arxiv_id = "";
                    if ($url =~ /arXiv\.(\d+\.\d+)/i) {
                        $arxiv_id = $1;
                    } elsif ($journal =~ /arXiv:(\d+\.\d+)/i) {
                        $arxiv_id = $1;
                    }
                    $output = "<wz tip=\"arXiv:$arxiv_id\">[[File:arXXXiv.png|14px|link=]]</wz><u>[[" . $bibkey . "|" . $title . "]]</u>. " . $output . "\{\{arXiv|$arxiv_id\}\} ([[" . $year . "]]).\n\n";
                } else {
                    $url =~ s/doi:/http:\/\/dx.doi.org\//;
                    $output = "<u>[[" . $bibkey . "|" . $title . "]]</u>. " . $output . "[[" . $journal . "]] [" . $url . " '''" . $volume . "''':" . $pages . "] ([[" . $year . "]]).\n\n";
                }

                # Apply existing substitutions
		$output =~ s/{{/XXXopenXXX/g;
		$output =~ s/}}/XXXcloseXXX/g;
                $output =~ s/, and/ and/g;
                $output =~ s/ +/ /g;
                $output =~ s/--/-/g;
                $output =~ s/{//g;
                $output =~ s/}//g;

		$output =~ s/\\"A/Ä/g;
		$output =~ s/\\"E/Ë/g;
		$output =~ s/\\"I/Ï/g;
		$output =~ s/\\"O/Ö/g;
		$output =~ s/\\"U/Ü/g;
		$output =~ s/\\"Y/Ÿ/g;
		$output =~ s/\\"a/ä/g;
		$output =~ s/\\"e/ë/g;
		$output =~ s/\\"i/ï/g;
		$output =~ s/\\"o/ö/g;
		$output =~ s/\\"u/ü/g;
		$output =~ s/\\"y/ÿ/g;
		$output =~ s/\\'A/Á/g;
		$output =~ s/\\'E/É/g;
		$output =~ s/\\'I/Í/g;
		$output =~ s/\\'O/Ó/g;
		$output =~ s/\\'U/Ú/g;
		$output =~ s/\\'Y/Ý/g;
		$output =~ s/\\'a/á/g;
		$output =~ s/\\'c/ć/g;
		$output =~ s/\\'e/é/g;
		$output =~ s/\\'i/í/g;
		$output =~ s/\\'l/ĺ/g;
		$output =~ s/\\'n/ń/g;
		$output =~ s/\\'o/ó/g;
		$output =~ s/\\'r/ŕ/g;
		$output =~ s/\\'s/ś/g;
		$output =~ s/\\'u/ú/g;
		$output =~ s/\\'y/ý/g;
		$output =~ s/\\'z/ź/g;
		$output =~ s/\\.Z/Ż/g;
		$output =~ s/\\.e/ė/g;
		$output =~ s/\\.g/ġ/g;
		$output =~ s/\\.z/ż/g;
		$output =~ s/\\=A/Ā/g;
		$output =~ s/\\=E/Ē/g;
		$output =~ s/\\=I/Ī/g;
		$output =~ s/\\=O/Ō/g;
		$output =~ s/\\=U/Ū/g;
		$output =~ s/\\=a/ā/g;
		$output =~ s/\\=e/ē/g;
		$output =~ s/\\=i/ī/g;
		$output =~ s/\\=o/ō/g;
		$output =~ s/\\=u/ū/g;
		$output =~ s/\\AA/Å/g;
		$output =~ s/\\AE/Æ/g;
		$output =~ s/\\DH/Ð/g;
		$output =~ s/\\HO/Ő/g;
		$output =~ s/\\HU/Ű/g;
		$output =~ s/\\Ho/ő/g;
		$output =~ s/\\Hu/ű/g;
		$output =~ s/\\L/Ł/g;
		$output =~ s/\\O/Ø/g;
		$output =~ s/\\OE/Œ/g;
		$output =~ s/\\TH/Þ/g;
		$output =~ s/\\`A/À/g;
		$output =~ s/\\`E/È/g;
		$output =~ s/\\`I/Ì/g;
		$output =~ s/\\`O/Ò/g;
		$output =~ s/\\`U/Ù/g;
		$output =~ s/\\`a/à/g;
		$output =~ s/\\`e/è/g;
		$output =~ s/\\`i/ì/g;
		$output =~ s/\\`o/ò/g;
		$output =~ s/\\`u/ù/g;
		$output =~ s/\\aa/å/g;
		$output =~ s/\\ae/æ/g;
		$output =~ s/\\c e/ę/g;
		$output =~ s/\\cC/Ç/g;
		$output =~ s/\\cc/ç/g;
		$output =~ s/\\cg/ģ/g;
		$output =~ s/\\ck/ķ/g;
		$output =~ s/\\cl/ļ/g;
		$output =~ s/\\cn/ņ/g;
		$output =~ s/\\cr/ŗ/g;
		$output =~ s/\\cs/ş/g;
		$output =~ s/\\ct/ţ/g;
		$output =~ s/\\dh/ð/g;
		$output =~ s/\\kA/Ą/g;
		$output =~ s/\\kE/Ę/g;
		$output =~ s/\\kI/Į/g;
		$output =~ s/\\kU/Ų/g;
		$output =~ s/\\ka/ą/g;
		$output =~ s/\\ke/ę/g;
		$output =~ s/\\ki/į/g;
		$output =~ s/\\ku/ų/g;
		$output =~ s/\\l/ł/g;
		$output =~ s/\\o/ø/g;
		$output =~ s/\\oe/œ/g;
		$output =~ s/\\ss/ß/g;
		$output =~ s/\\th/þ/g;
		$output =~ s/\\uA/Ă/g;
		$output =~ s/\\uE/Ĕ/g;
		$output =~ s/\\uG/Ğ/g;
		$output =~ s/\\uI/Ĭ/g;
		$output =~ s/\\uO/Ŏ/g;
		$output =~ s/\\uU/Ŭ/g;
		$output =~ s/\\ua/ă/g;
		$output =~ s/\\ue/ĕ/g;
		$output =~ s/\\ug/ğ/g;
		$output =~ s/\\ui/ĭ/g;
		$output =~ s/\\uo/ŏ/g;
		$output =~ s/\\uu/ŭ/g;
		$output =~ s/\\vA/Ǎ/g;
		$output =~ s/\\vC/Č/g;
		$output =~ s/\\vD/Ď/g;
		$output =~ s/\\vE/Ě/g;
		$output =~ s/\\vL/Ľ/g;
		$output =~ s/\\vN/Ň/g;
		$output =~ s/\\vR/Ř/g;
		$output =~ s/\\vS/Š/g;
		$output =~ s/\\vT/Ť/g;
		$output =~ s/\\vU/Ů/g;
		$output =~ s/\\vZ/Ž/g;
		$output =~ s/\\va/ǎ/g;
		$output =~ s/\\vc/č/g;
		$output =~ s/\\vd/ď/g;
		$output =~ s/\\ve/ě/g;
		$output =~ s/\\vl/ľ/g;
		$output =~ s/\\vn/ň/g;
		$output =~ s/\\vr/ř/g;
		$output =~ s/\\vs/š/g;
		$output =~ s/\\vt/ť/g;
		$output =~ s/\\vu/ů/g;
		$output =~ s/\\vz/ž/g;
		$output =~ s/\\~A/Ã/g;
		$output =~ s/\\~N/Ñ/g;
		$output =~ s/\\~O/Õ/g;
		$output =~ s/\\~a/ã/g;
		$output =~ s/\\~n/ñ/g;
		$output =~ s/\\~o/õ/g;
		$output =~ s/\\^A/Â/g;
		$output =~ s/\\^E/Ê/g;
		$output =~ s/\\^I/Î/g;
		$output =~ s/\\^O/Ô/g;
		$output =~ s/\\^U/Û/g;
		$output =~ s/\\^Y/Ŷ/g;
		$output =~ s/\\^a/â/g;
		$output =~ s/\\^e/ê/g;
		$output =~ s/\\^i/î/g;
		$output =~ s/\\^o/ô/g;
		$output =~ s/\\^u/û/g;
		$output =~ s/\\^y/ŷ/g;

                $output =~ s/\\Imamoglu/İmamoğlu/g;
                $output =~ s/\\Vuckovic/Vučković/g;
		$output =~ s/XXXopenXXX/{{/g;
		$output =~ s/XXXcloseXXX/}}/g;

                print $output;
                last;  # Exit inner loop once key is found
            }
        }
    }
}