Bib2wiki: Difference between revisions
Fabrice P. Laussy's Web
Fabrice (talk | contribs)
m 1 revision imported
 
(6 intermediate revisions by 3 users not shown)
Line 30: Line 30:
* v0°6 was written on {{thisday|22|October|2023}} to interface with [[keys2wiki]] (clearing the screen).
* 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}}.
* [[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


<syntaxhighlight lang="perl">
<syntaxhighlight lang="perl">
#! /usr/bin/perl -X -s  
#!/usr/bin/perl -X -s
# _    _ _    ____          _ _    _  
# _    _ _    ____          _ _    _  
#| |__ (_) |__|___ \__      _(_) | _(_)
#| |__ (_) |__|___ \__      _(_) | _(_)
Line 40: Line 47:
# F.P. Laussy - fabrice.laussy@gmailcom
# F.P. Laussy - fabrice.laussy@gmailcom
# v0°5 Sun 16 Jul 2023
# v0°5 Sun 16 Jul 2023
# v0°6 Sun 22 Oct 2023
# v0°7 Sun 31 Dec 2023 - http://laussy.org/wiki/Blog:Trifles/v0%C2%B07_of_bib2wiki
# 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
# Usage:
# v1.2 Sun Sep 21 - also process arXiv.bib
# To print one key:
# v1.3 Sun Sep 21 2025 - special formatting for arXiv entries
#   bib2wiki laussy04a
# v1.4 Sun Sep 21 2025 - fix <wz> tag placement
#
# v1.5 Sun Sep 21 2025 - fix {{arXiv}} template syntax
# To print several keys:
# v1.6 Mon Sep 22 2025 - all diatrics Grok can think of
#   bib2wiki -keys=laussy04a,laussy05a,laussy06a
#
# To print everything:
#   bib2wiki -keys=all


use BibTeX::Parser;
use BibTeX::Parser;
Line 64: Line 66:
open STDERR, '>', File::Spec->devnull();
open STDERR, '>', File::Spec->devnull();


# default file
# Concatenate sci.bib and arXiv.bib into an in-memory filehandle
my $fh  = IO::File->new("/home/laussy/Dropbox/Fabrice/bib/sci.bib");
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);
my $parser = BibTeX::Parser->new($fh);


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


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


while (my $entry = $parser->next ) {
# If keys is "all", process all entries in file order
    if ($entry->parse_ok) {
if ($keys eq "all") {
my $bibkey = $entry->key;
    while (my $entry = $parser->next) {
        if ($entry->parse_ok) {
if (($keys eq "all") or ($bibkey ~~ @mykeys)) {
            my $bibkey = $entry->key;
    my $type   = $entry->type;
            my $type = $entry->type;
    my $title   = $entry->field("title");
            my $title = $entry->field("title");
    my $url   = $entry->field("url");
            my $url = $entry->field("url") || "";
    $url =~ s/doi:/http:\/\/dx.doi.org\//;
            my $journal = $entry->field("journal") || "";
   
            my $volume = $entry->field("volume") || "";
    my $journal   = $entry->field("journal");
            my $pages = $entry->field("pages") || "";
    my $volume   = $entry->field("volume");
            my $year = $entry->field("year");
    my $pages   = $entry->field("pages");
    my $year   = $entry->field("year");
   
#     print $type . " -- " . $bibkey . "\n";
    print $bibkey . "\n";
#     my $output = "'''[" . $url . " " . $title . "]'''. ";
#     my $output = "<u>[[" . $title . "]]</u>. ";
    my $output = "<u>[[" . $bibkey . "|" . $title . "]]</u>. ";
   
    my @authors = $entry->author;
    # or:
    # my @editors = $entry->editor;
   
    # keep all but last authors
    my @notlast = @authors;
    pop @notlast;


    foreach my $author (@notlast) {
            print "\033[1;31m$bibkey\033[0m\n";
my $initials = $author->first;
            my $output = "";
$initials =~ s/~/ /g;
$output .= "[[" . $initials . " "
    . $author->von . " "
    . $author->last . "]], "
    ##                            . $author->jr;
    }


    # print last author
            my @authors = $entry->author;
    my $initials = $authors[-1]->first;
            my @notlast = @authors;
    $initials =~ s/~//g;
            pop @notlast;
    if (@notlast) { $output .= "and " };
    $output .= "[[" . $initials . " " . $authors[-1]->von . " " . $authors[-1]->last . "]] in ";
   
#     my $output = "'''[" . $url . " " . $title . "]'''. ";
    $output .= "[[" . $journal . "]] [" . $url . " '''" . $volume ."''':" . $pages . "] ([[" . $year . "]]).\n\n";


    $output =~ s/, and/ and/g;
            foreach my $author (@notlast) {
    $output =~ s/ +/ /g;
                my $initials = $author->first;
    $output =~ s/--/-/g;
                $initials =~ s/~/ /g;
    $output =~ s/{//g;
                $output .= "[[" . $initials . " " . $author->von . " " . $author->last . "]], ";
    $output =~ s/}//g;
            }
    $output =~ s/\\'a/á/g;
    $output =~ s/\\'e/é/g;
    $output =~ s/\\`e/è/g;
    $output =~ s/\\'o/ó/g;
    $output =~ s/\\"a/ä/g;
    $output =~ s/\\"o/ö/g;
    $output =~ s/\\"u/ü/g;
    $output =~ s/\\~n/ñ/g;
    $output =~ s/\\'E/É/g;


    # my macros
            my $initials = $authors[-1]->first;
    $output =~ s/\\Imamoglu/İmamoğlu/g;  
            $initials =~ s/~//g;
    $output =~ s/\\Vuckovic/Vučković/g;
            if (@notlast) { $output .= "and "; }
    print $output;
            $output .= "[[" . $initials . " " . $authors[-1]->von . " " . $authors[-1]->last . "]] in ";
}
 
    } else {
            # Check if the entry is from arXiv
warn "Error parsing file: " . $entry->error;
            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
            }
        }
     }
     }
}
}
</syntaxhighlight>
</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
            }
        }
    }
}