use strict;

open my $text, '<', 'test.txt';
$/ = $, = '['; # input record separator, output field separator
my %mapping; # existing endnote number --> number in ascendig order
my $endnote_counter = 1;

if (@ARGV && $ARGV[0] eq '--by_endnote_order') {
   while (<$text>) { # skip main text
       last if (/\@footnote:/);
   }
   while (<$text>) { # compute mapping in endnotes section
       if (/^(\d+)]/) {
           $mapping{$1} //= $endnote_counter++;
       }
   }
}

my @endnotes;
seek($text, 0, 0); # nop if not --by_endnote_order
while (<$text>) { # re-map endnote references in main text
   if (/^(\d+)(].*)$/ms) {
       $mapping{$1} //= $endnote_counter++; # nop if --by_endnote_order
       $_ = $mapping{$1}.$2;
   }
   print;
   last if (/\@footnote:/);
}
while (<$text>) { # re-order endnotes
   chomp;
   if (/^(\d+)(].*)$/ms) {
       $_ = $mapping{$1}.$2;
   }
   $endnotes[$mapping{$1}] .= ($endnotes[$mapping{$1}] ? '[' : q()) . $_;
}
print grep {$_} @endnotes; # omit endnote references without definition